I know that there are multiple questions about this already but none of them resolves my problem.
I have split my models into multiple files under models folder, viz., models/articles.py, models/core.py etc.
When I try executing
User.objects.annotate(my_count=Count('article'))
django gives me the following error:
FieldError: Cannot resolve keyword 'articles' into field. Choices are: access, cfi_store_item_likes, collaborators, comment, date_joined, documentation, email, emailaddress, first_name, groups, id, images, is_active, is_staff, is_superuser, last_login, last_name, listing, logentry, makey, makey_removed, newproduct, note, password, productdescription, productimage, profile, socialaccount, space_admins, space_members, textdocumentation, tutorial, user_permissions, userflags, username, video
I have the following code in models/abstract.py
class BaseModel(models.Model):
added_time = models.DateTimeField('added time')
is_enabled = models.BooleanField(default=True)
score = models.IntegerField(default=0)
class Meta:
abstract = True
app_label = 'catalog'
I have the following in models/article.py
class Article(BaseModel):
url = models.URLField()
title = models.CharField(max_length=500, null=True, blank=True)
description = models.TextField(null=True, blank=True)
image_url = models.URLField(null=True, blank=True)
rating = models.IntegerField()
recommendation = models.TextField(null=True, blank=True)
user = models.ForeignKey(User, null=True, blank=True)
tags = models.ManyToManyField(ArticleTag, null=True, blank=True)
comments = models.ManyToManyField(Comment, null=True, blank=True)
new_user = models.ForeignKey('NewUser', null=True, blank=True)
class Meta:
app_label = 'catalog'
def __unicode__(self):
return self.title + ' (' + self.url + ')'
I have the following in models/core.py, along with many other models which have been listed as the available options.
class Tutorial(BaseModel):
user = models.ForeignKey(User, null=True, blank=True)
description = models.CharField(max_length=200, null=True, blank=True)
url = models.URLField(max_length=200)
votes = models.IntegerField(default=0)
images = models.ManyToManyField(Image, related_name="tutorialimages",
null=True, blank=True)
class Meta:
app_label = 'catalog'
def __unicode__(self):
return self.url
Why is django not picking up my ForeignKey to User from models from rest of the files? Why is it picking it up only from core.py?
I have posted the models and stacktrace at http://pastebin.com/v6hFdvAC and http://pastebin.com/nxYktwHn.
Because not all users have an article. If you see, your user foreign key in Article Class can be null.
user = models.ForeignKey(User, null=True, blank=True)
then when Django tries to apply the count on null values, it raises an error.
Maybe you can use somehthing like that:
User.objects.objects.filter(article__isnull=False).count()
Related
I was trying to delete my Apllication model:
class Application(models.Model):
app_type = models.ForeignKey(ApplicationCategory, on_delete=models.CASCADE, related_name='applications')
fio = models.CharField(max_length=40)
phone_number = models.CharField(max_length=90)
organisation_name = models.CharField(max_length=100, null=True, blank=True)
aid_amount = models.PositiveIntegerField()
pay_type = models.CharField(max_length=1, choices=PAY_CHOICES, default=PAY_CHOICES[0][0])
status = models.ForeignKey(AppStatus, on_delete=models.CASCADE, related_name='applications', null=True, blank=True)
created = models.DateTimeField(auto_now_add=True)
benefactor = models.ForeignKey(Benefactor, on_delete=models.CASCADE, related_name='applications', null=True)
def __str__(self):
return f"id={self.id} li {self.fio} ning mablag\'i!"
and this was my Benefactor model:
class Benefactor(models.Model):
fio = models.CharField(max_length=255)
phone_number = models.CharField(max_length=9)
image = models.ImageField(upload_to='media/')
sponsory_money = models.IntegerField()
organisation_name = models.CharField(max_length=55, null=True, blank=True)
def __str__(self):
return f"{self.fio}"
But I got the below message on superAdmin Panel:
TypeError at /admin/api/benefactor/
create_reverse_many_to_one_manager.\<locals\>.RelatedManager.__call__() missing 1 required keyword-only argument: 'manager'
I would expect delete smoothly!!
Your Benefactor model has several ForeignKey relationships that share the related_name. Give each a unique name and rerun your migrations.
I also need the field (commentGroupDesc) from the foreign keys objects.
models.py
class commentGroup (models.Model):
commentGroup = models.CharField(_("commentGroup"), primary_key=True, max_length=255)
commentGroupDesc = models.CharField(_("commentGroupDesc"),null=True, blank=True, max_length=255)
def __str__(self):
return str(self.commentGroup)
class Meta:
ordering = ['commentGroup']
class Comment (models.Model):
commentID = models.AutoField(_("commentID"),primary_key=True)
commentUser = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
commentGroup = models.ForeignKey(commentGroup, on_delete=models.CASCADE, null=True)
commentCI = models.ForeignKey(Servicenow, on_delete=models.CASCADE, null=True)
commentText = RichTextField(_("commentText"), null=True, blank=True)
commentTableUpdated = models.CharField(_("commentTableUpdated"), null=True, blank=True, max_length=25)
def __str__(self):
return str(self.commentGroup)
class Meta:
ordering = ['commentGroup']
views.py
comment = Comment.objects.get(pk=commentID)
Here I get the commentGroup fine but I also need commentGroupDesc to put into my form.
At first, it's not a good thing to name same your model field as model name which is commentGroup kindly change field name, and run migration commands.
You can simply use chaining to get commentGroupDesc, also it's better to use get_object_or_404() so:
comment = get_object_or_404(Comment,pk=commentID)
group_desc = comment.commentGroup.commentGroupDesc
Remember to change field and model name first.
it only happens when I create new chatroom with the same admin
this is what I wrote in my models.py
class ChatRoom(models.Model):
id = models.UUIDField(primary_key=True, unique=True,
default=uuid.uuid4, editable=False)
name = models.CharField(max_length=100, null=False, blank=True)
users = models.ManyToManyField(User, through='Membership')
admin = models.ForeignKey(
User, null=False, blank=False, on_delete=models.CASCADE, related_name='admin')
date_created = models.DateTimeField(auto_now=True)
def __str__(self):
return self.name
class Membership(models.Model):
id = models.UUIDField(primary_key=True, unique=True,
default=uuid.uuid4, editable=False)
user = models.ForeignKey(User, on_delete=models.CASCADE)
chatroom = models.ForeignKey(ChatRoom, on_delete=models.CASCADE)
date_joined = models.DateTimeField(auto_now=True, null=False, blank=False)
def __str__(self):
return self.user
class Meta:
unique_together = [['user', 'chatroom']]
when i write this in the shell:
from .main.models import ChatRoom,Membership
from django.contrib.auth.models import User
user = User.objects.get(username = 'someone')
chatroom = ChatRoom(admin = user, name = 'something')
chatroom.save()
chatroom2 = ChatRoom(admin = user, name = 'somethingElse')
chatroom2.save()
after i save chatroom2 i get this error : django.db.utils.IntegrityError: UNIQUE constraint failed: main_chatroom.admin_id
can anyone help me?
so it turned out that i did something that made all migrations does not have any affect on the database
so i created new project and copied all my code to the new project( yes i know this is not the right way to do things but it was the easiest way for me) and everything now works great
I understand what Foreign Keys do but I'm having trouble understanding why this is working in Django.
I have the Project model in 'app1/models.py' file. This model has a ForeignKey named 'owner' that links to the Profile model in my 'app2/models.py' file.
How does the 'owner' field in the Project model know it should be linking to the 'user' field in the Profile model if I'm only passing the model name to the 'owner' field? I feel like I should be passing the Profile.field or something like this in the Project model:
owner = models.ForeignKey(Profile.user, null=True, blank=True ... )
Full model code from Dennis Ivy's tutorial:
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, null=True, blank=True)
name = models.CharField(max_length=200, blank=True, null=True)
email = models.EmailField(max_length=500, blank=True, null=True)
username = models.CharField(max_length=200, blank=True, null=True)
location = models.CharField(max_length=200, blank=True, null=True)
short_intro = models.CharField(max_length=200, blank=True, null=True)
bio = models.TextField(blank=True, null=True)
profile_image = models.ImageField(
null=True, blank=True, upload_to='profiles/', default='profiles/user-default.png')
social_github = models.CharField(max_length=200, blank=True, null=True)
social_twitter = models.CharField(max_length=200, blank=True, null=True)
social_linkedin = models.CharField(max_length=200, blank=True, null=True)
social_youtube = models.CharField(max_length=200, blank=True, null=True)
social_website = models.CharField(max_length=200, blank=True, null=True)
created = models.DateTimeField(auto_now_add=True)
id = models.UUIDField(default=uuid.uuid4, unique=True,
primary_key=True, editable=False)
class Project(models.Model):
owner = models.ForeignKey(Profile, null=True, blank=True, on_delete=models.SET_NULL)
title = models.CharField(max_length=200) #null is default=False and is required
description = models.TextField(null=True, blank=True) #for a bigger field, allows null(for db)/blank(for Django get/post)
featured_image = models.ImageField(null=True, blank=True, default='default.jpg')
demo_link = models.CharField(max_length=2000)
source_link = models.CharField(max_length=2000, null=True, blank=True) #can be blank in db
tags = models.ManyToManyField('Tag', blank=True) #quotes will ref other class after this one
vote_total = models.IntegerField(default=0, null=True, blank=True)
vote_ratio = models.IntegerField(default=0, null=True, blank=True)
created = models.DateTimeField(auto_now_add=True) #generate when model instance is created
id = models.UUIDField(default=uuid.uuid4, unique=True, primary_key=True, editable=False)
Foreign key fields do not match with another field in another model. it matches with the model itself.Let's say you want to assign a profile with the name 'victor' to new project model object, it would go like this:
from app_name.model import Project, Profile
profile1=Profile.objects.filter(name='victor').first()
new_project=Project(title='project 1',demolink='demo link',owner=profile1)
here, we assigned a user object to the owner property of the project and not a field.
The Profile.User field isn't necessary.
if you want to create a customUser, i suggest you should look that up or you'll be giving yourself many problems with authentication. You'll have to create a model manager for it after which you can begin to customise. It should look like this:
from django.db import models
from django.contrib.auth.models import User, AbstractUser
from django.utils.translation import ugettext_lazy as _
from django.contrib.auth.base_user import BaseUserManager
class CustomUserManager(BaseUserManager):
"""
Custom user model manager where email is the unique identifiers
for authentication instead of usernames.
"""
def create_user(self, username, password, **extra_fields):
"""
Create and save a User with the given username and password.
"""
if not username:
raise ValueError(_('The Username must be set'))
user = self.model(username=username, **extra_fields)
user.set_password(password)
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', False)
extra_fields.setdefault('is_active', True)
user.save()
return user
def create_superuser(self, username, password, **extra_fields):
"""
Create and save a SuperUser with the given username and password.
"""
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', True)
extra_fields.setdefault('is_active', True)
if extra_fields.get('is_staff') is not True:
raise ValueError(_('Superuser must have is_staff=True.'))
if extra_fields.get('is_superuser') is not True:
raise ValueError(_('Superuser must have is_superuser=True.'))
return self.create_user(username, password, **extra_fields)
class Profile(AbstractUser):
objects = CustomUserManager()
name = models.CharField(max_length=200, blank=True, null=True)
email = models.EmailField(max_length=500, blank=True, null=True)
location = models.CharField(max_length=200, blank=True, null=True)
short_intro = models.CharField(max_length=200, blank=True, null=True)
bio = models.TextField(blank=True, null=True)
profile_image = models.ImageField(
null=True, blank=True, upload_to='profiles/', default='profiles/user-default.png')
social_github = models.CharField(max_length=200, blank=True, null=True)
social_twitter = models.CharField(max_length=200, blank=True, null=True)
social_linkedin = models.CharField(max_length=200, blank=True, null=True)
social_youtube = models.CharField(max_length=200, blank=True, null=True)
social_website = models.CharField(max_length=200, blank=True, null=True)
created = models.DateTimeField(auto_now_add=True)
id = models.UUIDField(default=uuid.uuid4, unique=True,
primary_key=True, editable=False)
The field which has primary key is referenced by default if only setting a model name to "models.ForeignKey()" as mentioned in ForeignKey.to_field:
ForeignKey.to_field
...
By default, Django uses the primary key of the related object.
...
This is the full explanation of ForeignKey.to_field:
ForeignKey.to_field
The field on the related object that the relation
is to. By default, Django uses the primary key of the related object.
If you reference a different field, that field must have unique=True.
Thanks, Viq. I have solved my confusion now. The ForeignKey specifies a model but it always connects to that model's Primary Key which is why I don't have to specify Project.title or Project.id. Then when the Review model with the ForeignKey is output it calls the Project model's str method which lists out the title. I didn't realize the str method was being called.
I didn't include the str method in my code example because i didn't think that it had anything to do with my issue but I now understand that the str method is why I am seeing Project.title instead of Project.id.
def str(self): return self.title
This is the piece of the puzzle i was missing.
https://docs.djangoproject.com/en/3.2/ref/models/fields/#django.db.models.ForeignKey.to_field
ForeignKey.to_field
The field on the related object that the relation is to. By default, Django uses the primary key of the related object. If you reference a different field, that field must have unique=True.
I've been stuck on this for a few days (new to django) and can't figure out how to update skills for a specific user model using a ManyToManyField, while simultaneously updating a skill model containing a list of skills. Currently when I enter a value in my SkillForm, it updates the skill model properly and creates a dropdown list of skills for a given CustomUser in the admin. However, I can't figure out how to assign a SPECIFIC skill to a particular user. Any help is appreciated.
models.py:
class Skill(models.Model):
name = models.CharField(max_length =50, null=True, default='')
def __str__(self):
return self.name
class CustomUserManager(UserManager):
pass
class CustomUser(AbstractUser):
objects = CustomUserManager()
skills = models.ManyToManyField(Skill, null=True, blank=True)
position = models.CharField(max_length =50, null=True, default='')
bio = models.CharField(max_length=300, null=True, default='')
admin.py:
class SkillsInline(admin.StackedInline):
model = CustomUser.skills.through
class SkillAdmin(admin.ModelAdmin):
inlines = [SkillsInline ,]
UserAdmin.fieldsets += ('Custom fields set', {'fields': ('position', 'bio', )}),
class CustomUserAdmin(UserAdmin):
model = CustomUser
add_form = CustomUserCreationForm
form = EditProfile
inlines = [SkillsInline ,]
admin.site.register(CustomUser, CustomUserAdmin)
forms.py:
class SkillForm(forms.ModelForm):
name = forms.CharField()
class Meta:
model = Skill
fields =('name' ,)
def clean(self):
cleaned_data = super().clean()
name = cleaned_data.get('name')
I see somes problem here :
class CustomUser(AbstractUser):
objects = CustomUserManager()
skills = models.ManyToManyField(Skill, null=True, blank=True)
position = models.CharField(max_length =50, null=True, default='')
bio = models.CharField(max_length=300, null=True, default='')
When you define an AbstractUser` class, it's mean for Django Authentification purpose, see the doc here., dont do that because it's better to have an unique entry (each user have an unique entry, so you can login each one).
In your system you dont have unique CustomUser, here is a solution IMO:
class User(AbstractUser):
email = models.EmailField(_('email'), unique=True)
class UserAction(models.Model):
objects = CustomUserManager()
user = models.ForeignKey(User, verbose_name="User")
skills = models.ManyToManyField(Skill, null=True, blank=True)
position = models.CharField(max_length =50, null=True, default='')
bio = models.CharField(max_length=300, null=True, default='')
class Skill(models.Model):
name = models.CharField(max_length =50, null=True, default='')
def __str__(self):
return self.name
You now have an unique User, a list of UserAction that have a related Skill
user = User.objects.create(email='my#email.com')
skill = Skill.objects.create(name="shadow step")
user_action = UserAction.objects.create(user=user, skill=skill, position='HERE', bio='10')
Is that what you needed ?