models.py
class BaseComment(models.Model):
comment_author = models.ForeignKey(MyUser, related_name='written_comments')
comment_content = models.CharField(max_length=500)
comment_date = models.DateTimeField(auto_now_add=True)
rating = models.IntegerField(default=0)
users_voted = models.ManyToManyField(MyUser, related_name='voted_comments')
class Meta:
abstract = True
ordering = ['-comment_date']
def __unicode__(self):
return self.comment_author.email
class QuestionComment(BaseComment):
question = models.ForeignKey(Question, related_name='comments')
class AnswerComment(BaseComment):
answer = models.ForeignKey(Answer, related_name='comments')
This is my models.py. When I run syncdb, I get this error:
CommandError: One or more models did not validate:
app_quora.questioncomment: Accessor for field 'comment_author' clashes with rela
ted field 'MyUser.written_comments'. Add a related_name argument to the definiti
on for 'comment_author'.
app_quora.questioncomment: Reverse query name for field 'comment_author' clashes
with related field 'MyUser.written_comments'. Add a related_name argument to th
e definition for 'comment_author'.
app_quora.questioncomment: Accessor for m2m field 'users_voted' clashes with rel
ated m2m field 'MyUser.voted_comments'. Add a related_name argument to the defin
ition for 'users_voted'.
app_quora.questioncomment: Reverse query name for m2m field 'users_voted' clashe
s with related m2m field 'MyUser.voted_comments'. Add a related_name argument to
the definition for 'users_voted'.
app_quora.answercomment: Accessor for field 'comment_author' clashes with relate
d field 'MyUser.written_comments'. Add a related_name argument to the definition
for 'comment_author'.
app_quora.answercomment: Reverse query name for field 'comment_author' clashes w
ith related field 'MyUser.written_comments'. Add a related_name argument to the
definition for 'comment_author'.
app_quora.answercomment: Accessor for m2m field 'users_voted' clashes with relat
ed m2m field 'MyUser.voted_comments'. Add a related_name argument to the definit
ion for 'users_voted'.
app_quora.answercomment: Reverse query name for m2m field 'users_voted' clashes
with related m2m field 'MyUser.voted_comments'. Add a related_name argument to t
he definition for 'users_voted'.
Well, the error tells me to add the "related_name" for both "comment_author" and "users_voted", which I ALREADY DID!!. I looked up similar questions on stackoverflow, but usually the issue was that people didn't have this "related_name" for clashing fields.
I added this fields, but am still getting this error... Can someone explain why?
Thanks :(((
The problem you are seeing is because of the ForeignKey and ManyToManyField fields in the BaseComment model. Because it is an abstract model, django does not create a table for it.
However, the derived models QuestionComment and AnswerComment which inherit the fields try to add the same fields defined by related_name (written_comments , voted_comments ) in the MyUser model. Because you can have only one field with the same name it gives you those errors.
A solution would be to not have BaseComment as an abstract model and let it have its own table/model.
Or, you could add these fields in derived models.
You can also try not specifying related_name and let django decide the names, but I'm not sure if this will work or not.
Related
I'm trying to model a Many to Many Teacher/Student relationship. Both the teachers and the students are objects of class Users (I edited out some unrelated fields). I'm having problems in understanding how the relationship should work.
Basically, I want to be able to do something like
u1 = User.objects.get(pk=<student pk>)
u1.teachers.all()
u2 = User.objects.get(pk=<teacher pk>)
u2.students.all()
Is it possible?
After reading some docs and tutorials, this is how I defined the User class and the StudentTeacher relationship:
class User(AbstractUser):
is_student = models.BooleanField('student status', default=False)
is_teacher = models.BooleanField('teacher status', default=False)
teachers = models.ManyToManyField('self', through="StudentTeacher", through_fields=('student', 'teacher'), symmetrical=False)
students = models.ManyToManyField('self', through="StudentTeacher", through_fields=('teacher', 'student'), symmetrical=False)
class StudentTeacher(models.Model):
teacher = models.ForeignKey(User, related_name='students', on_delete=models.CASCADE, limit_choices_to={'is_teacher': True})
student = models.ForeignKey(User, related_name='teachers', on_delete=models.CASCADE, limit_choices_to={'is_student': True})
This is what happens when I try to generate migrations (wiscom is the name of my application):
wiscom.StudentTeacher.student: (fields.E302) Reverse accessor for 'StudentTeacher.student' clashes with field name 'User.teachers'.
HINT: Rename field 'User.teachers', or add/change a related_name argument to the definition for field 'StudentTeacher.student'.
wiscom.StudentTeacher.student: (fields.E303) Reverse query name for 'StudentTeacher.student' clashes with field name 'User.teachers'.
HINT: Rename field 'User.teachers', or add/change a related_name argument to the definition for field 'StudentTeacher.student'.
wiscom.StudentTeacher.teacher: (fields.E302) Reverse accessor for 'StudentTeacher.teacher' clashes with field name 'User.students'.
HINT: Rename field 'User.students', or add/change a related_name argument to the definition for field 'StudentTeacher.teacher'.
wiscom.StudentTeacher.teacher: (fields.E303) Reverse query name for 'StudentTeacher.teacher' clashes with field name 'User.students'.
HINT: Rename field 'User.students', or add/change a related_name argument to the definition for field 'StudentTeacher.teacher'.
wiscom.User.students: (fields.E304) Reverse accessor for 'User.students' clashes with reverse accessor for 'User.teachers'.
HINT: Add or change a related_name argument to the definition for 'User.students' or 'User.teachers'.
wiscom.User.teachers: (fields.E304) Reverse accessor for 'User.teachers' clashes with reverse accessor for 'User.students'.
HINT: Add or change a related_name argument to the definition for 'User.teachers' or 'User.students'.
You have far too many relationships here. You don't need the StudentTeacher model, and you only need a single ManyToManyField.
class User(AbstractUser):
students = models.ManyToManyField('self', symmetrical=False, related_name='teachers')
Now your code works exactly as you have given.
I'm new to Django and I've read many topics about authentication but I can't still figure out what is the best (or most used) way to set more account types in Django to be able to make different registrations.
Real Example:
I want to create a web page which is dedicated to provide communication and other services between customers and sellers (in this case people who translate across many languages).
The main point is this:
The web should be of course different for those two types of users.
Customer should not have to fill in forms like languages or price per hour during registration.
Another thing is that Seller should have access to pages like "Opened jobs" etc. and Customer should have access to pages like "Estimate price", "Upload text to translate" and many others.
I've already these models:
class Language(models.Model):
shortcut = models.CharField(max_length=6)
name = models.CharField(max_length=50)
price_per_sign = models.FloatField()
class BaseUser(AbstractUser):
# username = models.CharField(max_length=50)
# email = models.EmailField(unique=True)
# first_name = models.CharField(max_length=50)
# surname = models.CharField(max_length=50)
telephone = models.CharField(max_length=50)
class TranslatorUser(BaseUser):
languages = models.ManyToManyField(Language)
class Meta:
verbose_name = 'Translator'
verbose_name_plural = 'Translators'
class CustomerUser(BaseUser):
spent = models.FloatField()
class Meta:
verbose_name = 'Customer'
verbose_name_plural = 'Customers'
How to create a registration forms for both Customer and Translator?
This is my forms.py:
class TranslatorUserRegistrationForm(UserCreationForm):
username = forms.CharField(required=True)
email = forms.EmailField(required=True)
class Meta:
model = User
fields = ['email','username']
def save(self, commit=True):
user = super(TranslatorUserRegistrationForm,self).save(commit=True)
translator = TranslatorUser(user=user,email=self.cleaned_data['email'],username=self.cleaned_data['username'])
translator.save()
return user, translator
And views.py:
def register_translator(request):
form = TranslatorUserRegistrationForm()
if request.method==['POST']:
form = TranslatorUserRegistrationForm(request.POST)
else: return render(request,'registration/register_form.html',{'registration_form':form})
When I try to make migrations, it returns this error:
ERRORS:
auth.User.groups: (fields.E304) Reverse accessor for 'User.groups' clashes with
reverse accessor for 'BaseUser.groups'.
HINT: Add or change a related_name argument to the definition for 'User.
groups' or 'BaseUser.groups'.
auth.User.user_permissions: (fields.E304) Reverse accessor for 'User.user_permis
sions' clashes with reverse accessor for 'BaseUser.user_permissions'.
HINT: Add or change a related_name argument to the definition for 'User.
user_permissions' or 'BaseUser.user_permissions'.
auth_test.BaseUser.groups: (fields.E304) Reverse accessor for 'BaseUser.groups'
clashes with reverse accessor for 'User.groups'.
HINT: Add or change a related_name argument to the definition for 'BaseU
ser.groups' or 'User.groups'.
auth_test.BaseUser.user_permissions: (fields.E304) Reverse accessor for 'BaseUse
r.user_permissions' clashes with reverse accessor for 'User.user_permissions'.
HINT: Add or change a related_name argument to the definition for 'BaseU
ser.user_permissions' or 'User.user_permissions'.
Solution that I'm using is based on Profile models. Those are models that will extend normal user model (by one to one relation) and won't contain authentication data. That type of models are described in django docs, but they are made simply by OneToOneField.
I'm using solution based on model inheritance. In django models that aren't abstract also can be inherited, django will under the hood create OneToOneField in child model pointing to parent model. That field will also be used as an primary key, so ID of child model will always be same as it's parent. Also, you will be able to access parent fields from child models (like they we're here!).
So in other words, you should create 2 models (one for each type of user) that will inherit from standard User model (or customized one, but it can't be abstract) and for each registered user you will create object from one of that models.
For easy use, you can create middleware that will automatically detect type of user and swap user model in request object to specialized one.
I want created a kind social network for my school in django.
My Problem is that I create a follow function and django give me a Error Response.
How can I handle that?
django code:
class User(User):
joined = models.DateTimeField(auto_now_add=True)
is_activated = models.BooleanField(default=False)
def __unicode__(self):
return self.username
class Following_User(models.Model):
user_id = models.ForeignKey(User)
user_follow = models.ForeignKey(User)
and heres the Error Response:
ERRORS:
cherry.Following_User.user_follow: (fields.E304) Reverse accessor for 'Following_User.user_follow' clashes with reverse accessor for 'Following_User.user_id'.
HINT: Add or change a related_name argument to the definition for 'Following_User.user_follow' or 'Following_User.user_id'.
cherry.Following_User.user_id: (fields.E304) Reverse accessor for 'Following_User.user_id' clashes with reverse accessor for 'Following_User.user_follow'.
HINT: Add or change a related_name argument to the definition for 'Following_User.user_id' or 'Following_User.user_follow'.
System check identified 2 issues (0 silenced).
If you are having a model that contains two fields that as foreign key of another model, you need to specify the related_name for each of them.
class Following_User(models.Model):
user_id = models.ForeignKey(User, related_name="following_user_id")
user_follow = models.ForeignKey(User, related_name="following_user_follow")
https://docs.djangoproject.com/en/1.8/ref/models/fields/#django.db.models.ForeignKey.related_name
The reason to have related_name is so that django would give you reverse relation if you want to query from the foreign key. For single field that has the relationship with current model, django gives you a default one blahfield_set, but in this case the related_name would be used to remove ambiguity.
I'm currently building a helpdesk ticketing system as a school project. I am using the built in django auth system, and I'd like to refer to user IDs from the auth sytem. For example, a ticket will be assigned to a certain helpdesk employee. A part of my model:
class Ticket(models.Model):
category = models.ManyToManyField(Category)
title = models.CharField(max_length=30)
submitted = models.DateTimeField(editable=False)
submitter = #reference to user
assignedTo = #reference to helpdesk employee
Users are in the group user, helpdesk employees are in the group helpdeskemployee of the django auth system.
I already found this and this
So I tried this:
class Ticket(models.Model):
category = models.ManyToManyField(Category)
title = models.CharField(max_length=30)
submitted = models.DateTimeField(editable=False)
submitter = models.OneToOneField(User)
assignedTo = user = models.OneToOneField(User)
But that gives the folowing error while running python manage.py syncdb:
CommandError: One or more models did not validate:
deskman.ticket: Accessor for field 'submitter' clashes with related field 'User.ticket'. Add a related_name argument to the definition for 'submitter'.
deskman.ticket: Reverse query name for field 'submitter' clashes with related field 'User.ticket'. Add a related_name argument to the definition for 'submitter'.
deskman.ticket: Accessor for field 'assignedTo' clashes with related field 'User.ticket'. Add a related_name argument to the definition for 'assignedTo'.
deskman.ticket: Reverse query name for field 'assignedTo' clashes with related field 'User.ticket'. Add a related_name argument to the definition for 'assignedTo'.
deskman.ticket: Accessor for field 'assignedTo' clashes with related field 'User.ticket'. Add a related_name argument to the definition for 'assignedTo'.
deskman.ticket: Reverse query name for field 'assignedTo' clashes with related field 'User.ticket'. Add a related_name argument to the definition for 'assignedTo'.
Firstly, you probably don't want to use a OneToOneField. That would imply that a user can only ever have one single ticket. A ForeignKey relationship would be better.
class Ticket(models.Model):
category = models.ManyToManyField(Category)
title = models.CharField(max_length=30)
submitted = models.DateTimeField(editable=False)
submitter = models.ForeignKey(User)
assignedTo = models.ForeignKey(User)
The reason you are getting an error is that you have two relationships to the same model from your Ticket. This means if you have a User object and you are trying to reverse it, it's not clear via which relationship you want to use:
user.ticket_set.all()
# Do you want `submitter` tickets, or `assignedTo` tickets? It's not clear
To fix it, add a related_name attribute to each field
class Ticket(models.Model):
category = models.ManyToManyField(Category)
title = models.CharField(max_length=30)
submitted = models.DateTimeField(editable=False)
submitter = models.ForeignKey(User, related_name="tickets_submitter")
assignedTo = models.ForeignKey(User, related_name="tickets_assignedto")
Now you can get both reverse relationship separately:
user.tickets_submitter.all()
user.tickets_assignedto.all()
/mysite/project4
class notes(models.Model):
created_by = models.ForeignKey(User)
detail = models.ForeignKey(Details)
Details and User are in the same module i.e,/mysite/project1
In project1 models i have defined
class User():
......
class Details():
......
When DB i synced there is an error saying
Error: One or more models did not validate:
project4: Accessor for field 'detail' clashes with related field . Add a related_name argument to the definition for 'detail'.
How can this be solved..
thanks..
Gee we just had this one; and I answered...
You have a number of foreign keys which django is unable to generate unique names for.
You can help out by adding "related_name" arguments to the foreignkey field definitions in your models. Eg:
class notes(models.Model):
created_by = models.ForeignKey(User, related_name="note_created_by_user")
detail = models.ForeignKey(Details, related_name="noted_and_detailed")
See here for more. http://docs.djangoproject.com/en/dev/ref/models/fields/#django.db.models.ForeignKey.related_name