Learn Django - Build a Custom User Model with Extended Fields

Поделиться
HTML-код
  • Опубликовано: 15 янв 2025

Комментарии • 160

  • @kellystephen1785
    @kellystephen1785 4 года назад +13

    Your Django tutorials are the most detailed tutorials I have seen on RUclips. Thanks for sharing

    • @veryacademy
      @veryacademy  4 года назад +3

      Thank you, we have a few more gears to go through so please stick around for more detailed and hopefully better quality tutorials

    • @victormungai
      @victormungai 3 года назад +1

      @@veryacademy You can be sure I will... If the internet was coming down... I'd find a way to scrap your videos first

  • @syedibrahimbukhari7837
    @syedibrahimbukhari7837 2 года назад +8

    After following and failing at implementing the code form all the other tutorials, your tutorial was really simple, understandable and best of all it worked

  • @judevector
    @judevector 4 месяца назад +1

    In 2024 this video is still golden. I paused one of your video's because you mentioned this so i had to look for it and now i can comfortably say i have now gotten the knowledge i wanted ,let me resume your other video as well. Thanks alot ❤

  • @SmokeInYourScreen
    @SmokeInYourScreen 3 года назад +10

    I have been looking everywhere for a custom user tutorial. This is really amazing!

  • @karovda
    @karovda 4 года назад +9

    Everyone has already said this but this is A+ quality. Truly well done!

    • @veryacademy
      @veryacademy  4 года назад +2

      Thank you, always appreciative. It is exciting because this is not that good - over time much more to come.

  • @daidensacha
    @daidensacha 3 года назад +14

    Thanks for the brilliant tutorial. It was exactly what I was looking for, clear, concise, detailed.

  • @AHabib1080
    @AHabib1080 3 года назад +1

    Best best best.
    Thank you sir for making the perfect tutorial that I was looking for.

  • @pgallovich
    @pgallovich 3 года назад +3

    I'm so happy I found this channel. Awesome content! Thank you!

    • @veryacademy
      @veryacademy  3 года назад

      Welcome! Enjoy, any question, if I get time I will happily try and help

  • @aashayamballi
    @aashayamballi 4 года назад +4

    Custom user model and testing it. This channel is ❤️ 🤓
    Thank you 🙏🏼

    • @veryacademy
      @veryacademy  4 года назад

      Seems like a good way to introduce more testing!

  • @yasayah7289
    @yasayah7289 2 года назад +4

    Thank you! A 2nd part would be nice, along with admin approval before users can login.

  • @victormungai
    @victormungai 3 года назад +1

    watching this is just satisfying by itself... Thanks. This tutorial has expanded my thinking.

    • @veryacademy
      @veryacademy  3 года назад

      Thank you Victor for watching so intently.

  • @mgultas
    @mgultas 2 года назад +1

    This tutorial helped me a lot. Thank you, thank you, thank you.

    • @veryacademy
      @veryacademy  2 года назад

      Glad it helped! Thank you for the support!

  • @KevinTempelx
    @KevinTempelx 4 года назад +2

    Up and coming Django channel.

    • @veryacademy
      @veryacademy  4 года назад

      Thanks Kevin, will keep plugging away at Django 👍

  • @wilez493
    @wilez493 4 года назад +2

    You're just the best! gave a like but you deserve more so i subscribed! Thank you and keep it up!!

    • @veryacademy
      @veryacademy  4 года назад +1

      Thanks William, will try not to let you down 👍 Thanks for the sub

  • @ayman4047
    @ayman4047 2 года назад

    you are an artist by instinct

  • @srinivasasowmiyan2272
    @srinivasasowmiyan2272 3 года назад +3

    Thanks for the great work you have put in🙂 Happy that I found your channel 💖

  • @spatialnasir
    @spatialnasir 2 года назад

    This is a superbly done tutorial. Thanks so much.

  • @ivayloivanov3744
    @ivayloivanov3744 4 года назад +2

    Better than some of these paid tutorials! gj

  • @stanycastillo
    @stanycastillo 3 года назад +1

    Great tutorial. Thank you for sharing this valuable information. Regards

  • @Chocolanay
    @Chocolanay 4 года назад +2

    nice video bro. Very well explained.

  •  3 года назад +1

    Many, many thanks for that! Awesome tutorial!

  • @JosefWinter60
    @JosefWinter60 Год назад

    Thank you for this tutortial, did not know about the coverage package. 👍

  • @robertcoffie8789
    @robertcoffie8789 3 года назад +3

    Hi please thanks for the video , please why wasn't password field added to the NewUser() model fields thanks

    • @veryacademy
      @veryacademy  3 года назад +1

      AbstractUser is a full User model, complete with fields, as an abstract class so that you can inherit from it and add your own profile fields and methods. AbstractBaseUser only contains the authentication functionality, but no actual fields: you have to supply them when you subclass. So using AbstractBaseUser it adds the password fields for us when we migrate

    • @LcTheSecond
      @LcTheSecond 3 года назад +1

      just add 'password' in fieldsets
      fieldsets = (
      (None, {'fields': ('email', 'user_name', 'first_name', 'password')}),
      ('Permissões', {'fields': ('is_staff', 'is_active',)}),
      ('Pessoal', {'fields': ('about',)}),
      )

  • @CrossMax122
    @CrossMax122 4 года назад +5

    Great Video! I would love, however some follow up video with login/register templates! Of course liked and subscribed :)

  • @gagandangol467
    @gagandangol467 4 года назад +2

    thank you for these videos,

    • @veryacademy
      @veryacademy  4 года назад

      Thank you Gagan for the positive feedback!

  • @yashmore3525
    @yashmore3525 4 года назад

    Great tutorial! Waiting for the others!

  • @abdulrehmansohail2384
    @abdulrehmansohail2384 3 года назад

    Thanks for Saving my Job

  • @jithinrajmmwayanad4267
    @jithinrajmmwayanad4267 3 года назад +1

    thank you sir evey line is perfectly explained , no words to convey my happiness after grabbing the depth concept

  • @bakhodirrakhmatullayev1903
    @bakhodirrakhmatullayev1903 Год назад

    The great job, You saved my life😁

  • @damianrychlicki9945
    @damianrychlicki9945 3 года назад

    If I could I would give this video two thumbs up.

  • @valentim-aires
    @valentim-aires 4 года назад +2

    Great one!

    • @veryacademy
      @veryacademy  4 года назад

      Thanks João, just keep reminding me if I am getting slack with any of the series that you are watching and need more. I have quite a few on the go!

  • @berk_karaal
    @berk_karaal 3 года назад

    Great tutorial, thanks !

  • @rahulkmail
    @rahulkmail 2 года назад +1

    Excellent

  • @jhoanmartinezsilva2609
    @jhoanmartinezsilva2609 4 года назад +1

    Just a huge thank you

  • @austinhomolka
    @austinhomolka 3 года назад

    Great video. Thank you!

  • @ce.joseph
    @ce.joseph Год назад

    Very briliant tutorial Xander. I learnt a lot. How can we use the default auth forms with this custom user

  • @ricosun
    @ricosun 3 года назад +1

    Great Tute!

  • @databot3772
    @databot3772 4 года назад +2

    Do you have email confirmation tutorial, awesome classes :D

    • @veryacademy
      @veryacademy  4 года назад

      Think so! - If not I will do again

  • @KrishnaManohar8021
    @KrishnaManohar8021 4 года назад +2

    The sound was good! Implement Token Based Authentication also(Start Django-Rest-Framework(DRF) series)!?

  • @konstantingribanov7197
    @konstantingribanov7197 2 года назад

    just brilliant! especially about the tests in the end, very useful. If I can ask you a question why you are using an AbstractBaseUser instead of AbstractUser?

    • @veryacademy
      @veryacademy  2 года назад +1

      This might help: stackoverflow.com/questions/21514354/difference-between-abstractuser-and-abstractbaseuser-in-django

  • @josevelez6865
    @josevelez6865 4 года назад +4

    I have seen some code examples for custom user models where in the creation of a custom BaseUserManager class, instead of user.save(), they use user.save(using = self._db). Do you know what that is? I can't find anything in the Django docs about it.

    • @veryacademy
      @veryacademy  4 года назад +2

      stackoverflow.com/questions/57667334/what-is-the-value-of-self-db-by-default-in-django

  • @quadg1893
    @quadg1893 2 года назад

    Oh, my goodness! If I were a praying man, then my prayers have been answered. I've been performing a lot of "Google Fu" to find how to create a custom User model in order to have new Users enter more information about themselves than just 'username', 'password1', password2', 'email', 'first_name', and 'last_name', and I think I've found it! Thank you so much! (I haven't looked yet but I hope you have a tutorial about building a User authentication form.)

  • @TK-tg1hx
    @TK-tg1hx 2 года назад

    Thank you sooooooooooooo much!!!!!!!!!!!!!!

  • @anthonychianain2241
    @anthonychianain2241 Год назад

    Thanks so much

  • @marcelk.4371
    @marcelk.4371 10 месяцев назад +1

    Still very helpful! Thank you!
    Is there a chance to have a "change password" for the created users?

    • @veryacademy
      @veryacademy  10 месяцев назад

      To implement a feature in Django that allows users to change their passwords, you can follow these steps:
      Create a Password Change Form: First, you'll need to create a form where users can input their old password, new password, and confirm the new password.
      Implement a View for Password Change: Create a view that handles the password change process. This view will validate the old password, ensure that the new password meets the required criteria, and update the user's password if everything is valid.
      Map URLs: Map a URL to the password change view so that users can access it.
      Add Password Change Link: Add a link or button in your application's interface that directs users to the password change page.
      Here's an example implementation:
      Password Change Form (forms.py):
      python
      Copy code
      from django import forms
      from django.contrib.auth.forms import PasswordChangeForm as DjangoPasswordChangeForm
      class PasswordChangeForm(DjangoPasswordChangeForm):
      def __init__(self, user, *args, **kwargs):
      super().__init__(user, *args, **kwargs)
      self.fields['old_password'].widget.attrs.update({'class': 'form-control'})
      self.fields['new_password1'].widget.attrs.update({'class': 'form-control'})
      self.fields['new_password2'].widget.attrs.update({'class': 'form-control'})
      Password Change View (views.py):
      python
      Copy code
      from django.contrib.auth import update_session_auth_hash
      from django.contrib.auth.forms import PasswordChangeForm
      from django.contrib import messages
      from django.shortcuts import render, redirect
      def password_change(request):
      if request.method == 'POST':
      form = PasswordChangeForm(request.user, request.POST)
      if form.is_valid():
      user = form.save()
      update_session_auth_hash(request, user) # Important to update the session hash to prevent logout
      messages.success(request, 'Your password was successfully updated!')
      return redirect('password_change')
      else:
      form = PasswordChangeForm(request.user)
      return render(request, 'accounts/password_change.html', {'form': form})
      URL Configuration (urls.py):
      python
      Copy code
      from django.urls import path
      from .views import password_change
      urlpatterns = [
      path('password/change/', password_change, name='password_change'),
      # other paths...
      ]
      Template (password_change.html):
      html
      Copy code

      Password Change
      Password Change
      {% csrf_token %}
      {{ form.as_p }}
      Change Password
      Add Link in Template: In your application's template where users manage their account settings, add a link to the password change page:
      html
      Copy code
      Change Password
      With these steps, users should be able to change their passwords within your Django application. Ensure that you handle error messages and edge cases appropriately in your views and templates. Additionally, consider adding validation logic to ensure strong passwords and secure password change processes.

  • @elonmusk2142
    @elonmusk2142 4 года назад +1

    Thnkx bruh!!

    • @veryacademy
      @veryacademy  4 года назад

      Glad you found it useful 👍

  • @omotayoofere87
    @omotayoofere87 4 года назад +2

    While you were writing the tests, you imported the django's "get_user_model", why couldn't we import our custom model to test, since that's what we are actually testing?? Thank you.

    • @veryacademy
      @veryacademy  4 года назад +1

      Omotayo, without looking - the custom model was called from get_user_model because it is defined in the settings as the user model.

  • @yasinfakhar9091
    @yasinfakhar9091 3 года назад

    you are great man

  • @kifaru.
    @kifaru. Год назад

    Thanks very much for this wonderful tutorial, I really learnt a lot. I have a question. How do i add the groups and the user permission section in the admin panel?. I realise that the custom AdminUser did not add them. Thanks. I know this reply is 3 years late

  • @orkhanrustamli2039
    @orkhanrustamli2039 4 года назад +2

    Hi, thanks for videos. One question. I have seen the same thing in default Usermanager of Django in github. I wonder why to check "if extra_fields.get('is_staff') is not True" after setting defaults for them? Maybe I am misunderstood the meaning of "setdefault". As I understood it is to always setting the values of these fields. I just dont understand why to check them again after setting them?

    • @veryacademy
      @veryacademy  4 года назад

      It may just have been something I over looked - good find I will check the code - but, yeah no reason I can think of for doing that 👍

  • @computinginfo3187
    @computinginfo3187 4 года назад +2

    Great Vid!
    Could the fields be case-insensitive?
    Raise "Already exists" since "John" == "john"

    • @veryacademy
      @veryacademy  4 года назад +1

      Are you referring to CICharField (docs.djangoproject.com/en/3.0/ref/contrib/postgres/fields/)

  • @mursalrabb6093
    @mursalrabb6093 4 года назад +1

    Great tutorial and thank you so much for it!
    plus, waiting for a video on using mysql with django and also on multiple databases

  • @EdwardVarner
    @EdwardVarner 2 года назад +1

    What is the point / benefit of using REQUIRED_FIELDS vs null=False when declaring the field?

  • @ashoksharma7932
    @ashoksharma7932 2 года назад

    Great! But I have a question that whats difference between AbstractUser and AbstractBaseUser, Can you pls help me out.

  • @Stack_net
    @Stack_net 3 года назад

    it was be great 💖✔✔😎

  • @timothymalahy7880
    @timothymalahy7880 4 года назад +1

    Something I was confused by was the verbose name being done with gettext_lazy. It appears to me that you did the verbose_name based off position in the models.TextField() and models.EmailField() methods rather than explicitly typing verbose_name=gettext_lazy('email address').
    Is that correct? right around the 7:00 mark.

    • @veryacademy
      @veryacademy  4 года назад +1

      Hi Tim, you are right - just looking very quickly - I would be wanting to use verbose_name=_(... for verbose_name

  • @hasibullahwardak4514
    @hasibullahwardak4514 Год назад

    In 22:39
    after you add a new user with a password, as the password is not hashed;
    it doesn't login again.

  • @prvizpirizaditweb2324
    @prvizpirizaditweb2324 2 года назад +1

    is password field automatically created when we override default User model?

    • @veryacademy
      @veryacademy  2 года назад +1

      One would imagine that when we override a class we are provided with the original components and can override or add new elements. Sometimes it can be good to be explicit.

    • @NphiniT
      @NphiniT 2 года назад

      Yes it is

  • @phaniophrero8007
    @phaniophrero8007 2 года назад +1

    Thanks a lot for this tutorial , but I have a question though do you have a tutorial that kind of continues this with sending the email verification , password reset and resend email verification ? I've been following the django-graphql-auth tutorial too , but there I can't customize the register mutation like to have whatever field I want and still to be able to use their functionality of sending email verification, password resets and all of that good things... Do you have some video on that ?

  • @shalomirewole-ojo5335
    @shalomirewole-ojo5335 3 года назад

    Please what about the video that deals with linking to this CustomUser model. The signal and AUTH_USER_MODEL stuff?

  • @what-the-code
    @what-the-code 2 года назад +1

    How to use two field combination as username like firstname_lastname?

    • @veryacademy
      @veryacademy  2 года назад

      It is worth doing that?

    • @what-the-code
      @what-the-code 2 года назад

      @@veryacademy i have legacy table employee detail. Have not any email or username field. I have to combine 2 field to create unique.

    • @NphiniT
      @NphiniT 2 года назад

      @@what-the-code And you think firstname and lastname is unique to every single person?

  • @sizu257
    @sizu257 2 года назад +1

    After 16 minutes of tutorial, I realize that is_super_teacher = True.

    • @veryacademy
      @veryacademy  2 года назад

      Thank you. It doesn't always come out good but, I try.

  • @rajughorai3909
    @rajughorai3909 3 года назад +1

    add_fieldsets not showing anything on mine

    • @veryacademy
      @veryacademy  3 года назад

      Hi Raju, I tested the code - seems ok. Just double, triple check your code 👍

  • @joey4uandme
    @joey4uandme 9 месяцев назад

    How would you advise me to extend the user model for a shop, the user roles are shop owner or admin, marketers and vendors. Vendors don't post products they just handle orders. Marketers are like regular customer who sell offline so they make orders.

  • @NadidLinchestein
    @NadidLinchestein 3 года назад

    zsh: command not found: coverage
    I keep getting error even though I have it installed and I tried so many times but this error just doesn't goes awayyy

  • @georgesmith3022
    @georgesmith3022 3 года назад

    If i want to create two new classes, like teachers and students, is it better to subclass newuser or create a one-to-one relationship with newuser class?

    • @NphiniT
      @NphiniT 2 года назад

      I would create a one-to-one relationship and use signals to create the teacher and student classes after new user is created

  • @254_Cyrus
    @254_Cyrus 3 года назад

    Hello thanks again for the tutorial Very Academy. Just a quick question, my frontend allows Google and Twitter Sign In's. How can I make the password field nullable when say custommodel.usertype == 'Google'. Meaning when user signs in with Google in the FrontEnd we don't need to store a password for that user. Tried reading the docs but couldn't quite understand how to go about it. Will really appreciate your help.
    Thanks for the tutorials, keep em coming.

  • @Neojagz
    @Neojagz 2 года назад

    I.m getting an error django.core.exceptions.ImproperlyConfigured: AUTH_USER_MODEL refers to model 'users.NewUser' that has not been installed. Please what dod i do?

  • @justinmann8331
    @justinmann8331 4 года назад +1

    Your videos are an absolute blessing! One question, when I go to create my migrations I get: AttributeError saying my custom user model has no attribute 'EMAIL_FIELD'

    • @justinmann8331
      @justinmann8331 4 года назад

      Any ideas?

    • @justinmann8331
      @justinmann8331 4 года назад +1

      I added the 'EMAIL_FIELD' and set it to the 'email' and new errors come

    • @veryacademy
      @veryacademy  4 года назад +1

      class User(AbstractUser):
      """User model."""
      username = None
      email = models.EmailField(unique=True)
      EMAIL_FIELD = 'email'
      code above if you are using Abstract user - define the email - you need to add it in the class like above

  • @josevelez6865
    @josevelez6865 4 года назад +1

    I don't think the formfield_override for 'about' is working. Does it work on yours? A quick google search brings up needing to create a form that extends ModelForm to make it work.

    • @veryacademy
      @veryacademy  4 года назад

      Hi again. Can you point me to the part of the tutorial where you think it is not working please I will take a look. - Ok I tested it on my computer from the repository - everything seem to work - What isnt working on your end?

    • @josevelez6865
      @josevelez6865 4 года назад

      @@veryacademy Around 25:44 it was added but I never saw you test it so I could not confirm if I was doing something wrong or not.

    • @veryacademy
      @veryacademy  4 года назад +1

      Just an optional field to prompt anyone who needed it that they could extend the table as per normal

  • @mohammadg5326
    @mohammadg5326 3 года назад +1

    hi, thanks for this tutorail. I followed all of your step. Found success in it. But there is an error and I cant resolve it. When I try to register a user from admin panel. The user is created but its password is not stored in hash format. Any idea, how can I resolve it?

    • @abhinaysingh5059
      @abhinaysingh5059 2 года назад

      bro i'm facing the same bug, did you find any solution...?

    • @mohammadg5326
      @mohammadg5326 2 года назад

      @@abhinaysingh5059 yeah bro, the make_password method. they store the password in hash

    • @mohammadg5326
      @mohammadg5326 2 года назад

      @@abhinaysingh5059 def create_superuser(self, email, user_name, password, **other_fields):
      other_fields.setdefault('is_staff', True)
      other_fields.setdefault('is_superuser', True)
      other_fields.setdefault('is_active', True)
      return self.create_user(email, user_name, password, **other_fields)
      def create_user(self, email, user_name, password, **other_fields):
      if not email:
      raise ValueError('Email is Required !!')
      email = self.normalize_email(email)
      user = self.model(email=email, user_name=user_name, **other_fields)
      user.set_password(password)
      user.save(using=self._db)
      return user

  • @mertardaasar4376
    @mertardaasar4376 3 года назад

    I am getting an error like "AttributeError: Manager isn't available; 'auth.User' has been swapped for 'Pollapp.NewUser'"

    • @NphiniT
      @NphiniT 2 года назад +1

      I had a similar error when I was creatnig a custom user in an project. So my initial migrations caused this. Delete the migrations in the other apps using the user model and delete the sqlite file. Then run migrations again. That resolved it for me

  • @karnashubham2698
    @karnashubham2698 3 года назад

    Hello good sir. First of all, thankyou very much for this informative video, its been a great help. The one thing I'd like to ask is, how could i set the username as username instead of email as username for superuser login?

  • @omotayoofere5504
    @omotayoofere5504 4 года назад +1

    Great tutorial, however, when I tried to implement with some different user model fields, everything worked perfectly till I tried logging in as a superuser in the admin page, it returned "Please enter the correct reg no and password for a staff account. Note that both fields may be case-sensitive.", even after multiple superusers was created. Kindly assist.

    • @veryacademy
      @veryacademy  4 года назад

      Hey Omotayo, it is a tricky one to suggest based on what you have said. Really sorry - Take it back a few steps and try and see the pattern of working - like you said you added some more fields - so just backward engineer it - takes time but you will get a better understanding

  • @yelinthu7367
    @yelinthu7367 3 года назад

    I could not update is_active field to "True" with is_active = models.BooleanField(default=True) in UserAccountManager then Is Active is always shown as false at Django-admin panel . Please guide me that what i need to do

  • @neharamakanth6796
    @neharamakanth6796 4 года назад

    What is the difference between add_fieldsets and fieldsets in Django Admin customization ?Could you please explain about this

    • @roguesoul62
      @roguesoul62 4 года назад +2

      Fieldsets are rendered when you go to change existing user detail (when you click on user in admin users list page) whereas add_fieldsets are rendered when you are adding new user (when you click “+” or click “add user”)

    • @neharamakanth8073
      @neharamakanth8073 4 года назад

      @@roguesoul62 Thank you so much

  • @Chocolanay
    @Chocolanay 4 года назад +1

    I was trying out coverage, however, it does not 'detect' the test I've created for my custom user model. I have two test cases, but coverage reports 0 test run. I was following everything here but I still couldn't make it work. Do you have any idea how can I force coverage to run on the 'app' level if that makes sense... I'm using pipenv not venv.
    EDIT:
    Nevermind. Got it.
    Just added the app name after 'coverage run test appname'

    • @veryacademy
      @veryacademy  4 года назад

      Seems a little strange, likely a naming problem?

    • @Chocolanay
      @Chocolanay 4 года назад

      @@veryacademy I don't really know. I'll explore a bit later. Running the test while specifying every app is troublesome and annoying.

  • @kushagraaagnihotri1081
    @kushagraaagnihotri1081 3 года назад

    i am unable to login 'Please enter the correct email address and password for a staff account. Note that both fields may be case-sensitive.'

  • @ajinzrathod
    @ajinzrathod 3 года назад

    Hey I don't understand one thing.
    "is_superuser" was not defined in class .
    But in function , you are using it as
    other_fields.setdefault('is_superuser', True)
    How?
    -------------
    I even added "is_superuser" in fields and it is treating it as inbuilt superuser column.
    ('Permissions', {'fields': ('is_staff', 'is_active', 'is_superuser', )}),
    I don't get this.

    • @NphiniT
      @NphiniT 2 года назад +1

      The PermissionsMixin is what sets the is_superuser field.

  • @MrKareem722
    @MrKareem722 2 года назад

    Thank you for the greate Tutorial, as usual, though I got an error while migrate "django.db.migrations.exceptions.InconsistentMigrationHistory: Migration admin.0001_initial is applied before its dependency NewUser.0001_initial on database 'default'." the app NewUser I am using was already there before I follow your tutorial but I have changed everything as per your steps, and still on sqlite.

    • @MrKareem722
      @MrKareem722 2 года назад

      changed Database to PosgreSQL and problem solved, I am curius about the reason though.

  • @webseries9482
    @webseries9482 3 года назад

    Your thumblin bring mw

  • @yogeshjadhav5468
    @yogeshjadhav5468 3 года назад

    With this method, every user that I create gets all permissions automatically. How can I limit permissions while creating new user?

    • @derekkroeker4582
      @derekkroeker4582 3 года назад

      Have you tried groups?

    • @yogeshjadhav5468
      @yogeshjadhav5468 3 года назад

      @@derekkroeker4582 Thank you for your revert. No i haven't tried groups yet. I am using with DRF. do I need to create users with groups?

  • @tusharhegde
    @tusharhegde Год назад +1

    I like your voice

  • @ac11dc110
    @ac11dc110 3 года назад

    6 php devs disliked the video

  • @spatialnasir
    @spatialnasir 2 года назад

    This is a superbly done tutorial. Thanks so much.