CRUD code feedback

41 views
Skip to first unread message

tango ward

unread,
Jan 27, 2018, 8:40:31 PM1/27/18
to django...@googlegroups.com

Hi,

I am playing around with CRUD. I want a user a create an account first before he/she can add pets under his/her profile. I tried adding one pet however it's seems that it is not associated to the Owner who added the pet.

models.py

from django.db import models
from django.contrib.auth.models import User, PermissionsMixin
from django.urls import reverse
# Create your models here.


class Owner(User, PermissionsMixin):

    def __str__(self):
        return self.username


class Cat(models.Model):
    name = models.CharField(max_length=40)
    bday = models.DateField()
    owner = models.ForeignKey(Owner, related_name='cats', null=True, on_delete=models.SET_NULL)

    def get_absolute_url(self):
        return reverse('test')

    def __str__(self):
        return self.name


class Dog(models.Model):
    name = models.CharField(max_length=40)
    bday = models.DateField()
    owner = models.ForeignKey(Owner, related_name='dogs', null=True, on_delete=models.SET_NULL)

    def get_absolute_url(self):
        return reverse('test')

    def __str__(self):
        return self.name


Any suggestions will be highly appreciated.


Regards,
Jarvis

Akhil Lawrence

unread,
Jan 27, 2018, 10:49:18 PM1/27/18
to Django users
Hi Jarvis,

The code which you have posted only shows the model. Within your cat and dog models the owner can be null. Which explains why the owner is not associated with the pets. Can I see the code you tried to insert the records?

## changes needed in models
models.ForeignKey(Owner, related_name='cats', on_delete=models.CASCADE)
models.ForeignKey(Owner, related_name='dogs', on_delete=models.CASCADE)

## code for inserting records
owner = Owner.objects.create_user(username="blah", password="blah", email="bl...@blah.com")
dog = Dog(name="mydog", bday=datetime.today(), owner=owner).save()


Thanks.

tango ward

unread,
Jan 27, 2018, 11:55:59 PM1/27/18
to django...@googlegroups.com
Hi,

Thanks for the response Akhil,

I am using the CreateView in my view.py to create ne pets


class CreateDog(CreateView):
    model = Dog
    fields = ('name', 'bday')
    template_name = 'animals/dog_create.html'


class CreateCat(CreateView):
    model = Cat
    fields = ('name', 'bday')
    template_name = 'animals/cat_create.html'



--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.
To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/8f31afb0-2a9d-49ef-94b4-213aef140cf2%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Akhil Lawrence

unread,
Jan 28, 2018, 12:11:03 AM1/28/18
to Django users
Your create view do not accept owner as a input and according to your models, owner can be null. That's the problem. Include owner to your create view fields as shown below. Also you may consider making owner mandatory as mentioned in my previous response.


class CreateDog(CreateView):
model = Dog

fields = ('name', 'bday', 'owner')
template_name = 'animals/dog_create.html'


class CreateCat(CreateView):
model = Cat

fields = ('name', 'bday', 'owner')
template_name = 'animals/cat_create.html'

Thanks

tango ward

unread,
Jan 28, 2018, 12:13:54 AM1/28/18
to django...@googlegroups.com
Will try it now.

Quesion about the on_delete=models.CASCADE, does this mean that if I delete the pet (dog or cat) it will delete the owner who owns them?

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.
To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.

tango ward

unread,
Jan 28, 2018, 12:48:28 AM1/28/18
to django...@googlegroups.com
When I added the owner field, it doesn't have any value though the user is already registered.

how do i make it mandatory in createview?



owner = Owner.objects.create_user(username="blah", password="blah", email="bl...@blah.com")
dog = Dog(name="mydog", bday=datetime.today(), owner=owner).save()

Akhil Lawrence

unread,
Jan 28, 2018, 1:06:36 AM1/28/18
to Django users
Its the reverse. If the owner is deleted, all the cats and dogs associated with the owner will be deleted.


On Sunday, 28 January 2018 10:43:54 UTC+5:30, tangoward15 wrote:
Will try it now.

Quesion about the on_delete=models.CASCADE, does this mean that if I delete the pet (dog or cat) it will delete the owner who owns them?
On Sun, Jan 28, 2018 at 1:11 PM, Akhil Lawrence <akhilp...@gmail.com> wrote:
Your create view do not accept owner as a input and according to your models, owner can be null. That's the problem. Include owner to your create view fields as shown below. Also you may consider making owner mandatory as mentioned in my previous response.


class CreateDog(CreateView):
    model = Dog
    fields = ('name', 'bday', 'owner')
    template_name = 'animals/dog_create.html'


class CreateCat(CreateView):
    model = Cat
    fields = ('name', 'bday', 'owner')
    template_name = 'animals/cat_create.html'

Thanks

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users...@googlegroups.com.

To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.

Akhil Lawrence

unread,
Jan 28, 2018, 1:18:31 AM1/28/18
to Django users
There are two ways to do this. 

1. You can set the owner as the logged in user by default
2. You can provide all possible owners as options and the user can select the owner from a dropdown.

For case 1, you may not want to display the owner field in frontend. Here you can override form_valid and set the owner as logged in user.

class CreateDog(CreateView):
    .......
    def form_valid(self, form):
        form.instance.owner = self.request.user
        return super(CreateDog, self).form_valid(form)

For more details:


For case 2, you need to populate the list of owners by overriding the get_initial method.

class CreateDog(CreateView):
    .......
    def get_initial(self):
        initial_data = super(CreateDog, self).get_initial()
        initial_data["owner"] = [(x.id, x.name) for x in Owner.objects.all()]
        return initial_data

For more details:

On Sunday, 28 January 2018 11:18:28 UTC+5:30, tangoward15 wrote:
When I added the owner field, it doesn't have any value though the user is already registered.

how do i make it mandatory in createview?


owner = Owner.objects.create_user(username="blah", password="blah", email="bl...@blah.com")
dog = Dog(name="mydog", bday=datetime.today(), owner=owner).save()

On Sun, Jan 28, 2018 at 1:13 PM, tango ward <tango...@gmail.com> wrote:
Will try it now.

Quesion about the on_delete=models.CASCADE, does this mean that if I delete the pet (dog or cat) it will delete the owner who owns them?
On Sun, Jan 28, 2018 at 1:11 PM, Akhil Lawrence <akhilp...@gmail.com> wrote:
Your create view do not accept owner as a input and according to your models, owner can be null. That's the problem. Include owner to your create view fields as shown below. Also you may consider making owner mandatory as mentioned in my previous response.


class CreateDog(CreateView):
    model = Dog
    fields = ('name', 'bday', 'owner')
    template_name = 'animals/dog_create.html'


class CreateCat(CreateView):
    model = Cat
    fields = ('name', 'bday', 'owner')
    template_name = 'animals/cat_create.html'

Thanks

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users...@googlegroups.com.

To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.

tango ward

unread,
Jan 28, 2018, 1:22:31 AM1/28/18
to django...@googlegroups.com
I updated my models. py

from django.db import models
from django.contrib.auth import get_user_model

from django.contrib.auth.models import User, PermissionsMixin

# Create your models here.


Pet_Owner = get_user_model()


class RegisteredUser(User, PermissionsMixin):

    def __str__(self):
        return self.username


class Dog(models.Model):
    name = models.CharField(max_length=40)
    bday = models.DateField()
    owner = models.ForeignKey(Pet_Owner, related_name='dogs', on_delete=models.CASCADE)

    def __str__(self):
        return self.name + ' - ' + str(self.owner)



class Cat(models.Model):
    name = models.CharField(max_length=40)
    bday = models.DateField()
    owner = models.ForeignKey(Pet_Owner, related_name='cats', on_delete=models.CASCADE)

    def __str__(self):
        return self.name + ' - ' + str(self.owner)


I can see all users as drop down list for owner field using Pet_Owner = get_user_model() .Problem is, it shows all the Users in the project not the only one who is currently logged in.

To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.

To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.

Akhil Lawrence

unread,
Jan 28, 2018, 1:31:21 AM1/28/18
to Django users

override get_initial and set only the logged in user

class CreateDog(CreateView):
    .......
    def get_initial(self):
        initial_data = super(CreateDog, self).get_initial()
        initial_data["owner"] = [(self.request.user.id, self.request.user.username)]
        return initial_data

tango ward

unread,
Jan 28, 2018, 1:59:58 AM1/28/18
to django...@googlegroups.com
Sorry for being a drag, I tried this code:

class CreateDog(CreateView):
    template_name = 'dogs_cats/create_dog.html'

    model = Dog
    fields = ('name', 'bday', 'owner')

    def get_initial(self):
        initial_data = super(CreateDog, self).get_initial()
        initial_data["owner"] = [(self.request.user.id, self.request.user.username)]
        return initial_data


still I am getting the Admin user in the drop down list for owner.

To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.

To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.

Akhil Lawrence

unread,
Jan 28, 2018, 2:20:04 AM1/28/18
to Django users
I doubt whether you are reading my response properly. Let me reiterate my response for you.


There are two ways to do this. 

1. You can set the owner as the logged in user by default
2. You can provide all possible owners as options and the user can select the owner from a dropdown.

For case 1, you may not want to display the owner field in frontend. Here you can override form_valid and set the owner as logged in user.

class CreateDog(CreateView):
    .......
    def form_valid(self, form):
        form.instance.owner = self.request.user
        return super(CreateDog, self).form_valid(form)

For more details:


For case 2, you need to populate the list of owners by overriding the get_initial method.

class CreateDog(CreateView):
    .......
    def get_initial(self):
        initial_data = super(CreateDog, self).get_initial()
if you don't want to show the owner and want to associate the pet with owner via backend go for option1 (also note that you may need to remove the owner from fields of your createview)
if you want to show a dropdown of possible owners go for option 2.

If you need further assistance, please share your screen via chrome remote desktop or something and lets solve it

Thanks.

tango ward

unread,
Jan 28, 2018, 4:33:39 AM1/28/18
to django...@googlegroups.com
Thanks, I'm digesting it. I am going to use the first option.

To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.

To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.

tango ward

unread,
Jan 28, 2018, 8:07:08 AM1/28/18
to django...@googlegroups.com
Sorry, for asking again. In option one, It appears that I am getting an error for using the owner field which is a ForeignKey.

"
"<SimpleLazyObject: <User: owner2>>": "Dog.owner" must be a "User" instance."


class CreateDog(CreateView):
    template_name = 'dogs_cats/create_dog.html'
    model = Dog
    fields = ('name', 'bday')


    def form_valid(self, form):
        form.instance.owner = self.request.user
        return super(CreateDog, self).form_valid(form)


I looked at StackOverflow and saw this thread https://stackoverflow.com/questions/30017334/django-foreign-key-must-be-an-instance. Is there a way to use the same solution in side the form_valid()?


Akhil Lawrence

unread,
Jan 28, 2018, 9:02:35 AM1/28/18
to Django users
This error message is tricky.

According to your model definition owner is of type Owner. This error message actually comes from the Owner model.

Instead of  form.instance.owner = self.request.user, try  form.instance.owner = Owner(id=self.request.user.id)

It should work.

tango ward

unread,
Jan 28, 2018, 9:17:40 AM1/28/18
to django...@googlegroups.com

Now I am getting this error

"save() prohibited to prevent data loss due to unsaved related object 'owner'."

Really appreciate you're help/suggestions. My first time to mess around with CRUD with user registration, login, logout.

To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.

To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.

Akhil Lawrence

unread,
Jan 28, 2018, 9:20:14 AM1/28/18
to Django users
Oops I missed something, you are creating a different table all together for Owner. In that case you need to insert owner record (This is not recommended, since the data is going to be the exact copy of User. This will cause data inconsistency, use User instead)

class CreateDog(CreateView):
    template_name = 'dogs_cats/create_dog.html'
    model = Dog
    fields = ('name', 'bday')


    def form_valid(self, form):
        owner = Owner.objects.create_user(self.request.user.username, self.request.user.email, self.request.user.password)
        form.instance.owner = owner
        return super(CreateDog, self).form_valid(form)

But I would say this approach is wrong, your Owner is exact copy of User. Use User instead.

The ideal way should be,

class Cat(models.Model):
    name = models.CharField(max_length=40)
    bday = models.DateField()
    owner = models.ForeignKey(User, related_name='cats', on_delete=models.CASCADE)


class CreateDog(CreateView):
    template_name = 'dogs_cats/create_dog.html'
    model = Dog
    fields = ('name', 'bday')

    def form_valid(self, form):
        form.instance.owner = self.request.user
        return super(CreateDog, self).form_valid(form)

tango ward

unread,
Jan 28, 2018, 9:40:38 AM1/28/18
to django...@googlegroups.com
I am getting another error:
Cannot assign "<SimpleLazyObject: <django.contrib.auth.models.AnonymousUser object at 0x7fe3fa28fe48>>": "Dog.owner" must be a "User" instance.
models.py

from django.db import models
from django.contrib.auth import get_user_model
from django.contrib.auth.models import User, PermissionsMixin
from django.urls import reverse



# Create your models here.


class RegUser(User, PermissionsMixin):

    def __str__(self):
        return "@{}".format(self.username)



class Dog(models.Model):
    name = models.CharField(max_length=40)
    bday = models.DateField()
    owner = models.ForeignKey(User, related_name='dogs', on_delete=models.CASCADE)

    def __str__(self):
        return self.name


views.py


class CreateDog(CreateView):
    template_name = 'dogs_cats/create_dog.html'
    model = Dog
    fields = ('name', 'bday')

    def form_valid(self, form):
        form.instance.owner = self.request.user
        return supter(CreateDog, self).form_valid(form)

To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.

To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.

Akhil Lawrence

unread,
Jan 28, 2018, 9:59:00 AM1/28/18
to Django users
The takeaway from the above error is AnonymousUser

This means you are not logged into the system. By default self.request.user will be an instance of AnonymousUser,
the moment you login it becomes User instance

Make sure you login before hitting this code

Thanks.

tango ward

unread,
Jan 28, 2018, 10:05:48 AM1/28/18
to django...@googlegroups.com
Holy smoke it's working!!!

Thanks a lot!

I can use the same pattern for update and delete right?

To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.

To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.

Akhil Lawrence

unread,
Jan 28, 2018, 10:32:33 AM1/28/18
to Django users
Happy to see that you were able to get it in working condition. Cheers !!!!

tango ward

unread,
Jan 28, 2018, 10:34:37 AM1/28/18
to django...@googlegroups.com
Thanks a lot for your help and patience. I really appreciate it!

To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.

To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
Reply all
Reply to author
Forward
0 new messages