Why is it throwing an Django- Reverse query name SystemCheckError? - python

I am a newbie to Django, While running the django application using python3 manage.py runserver
Because of the way I have created the model I am getting an error like
django.core.management.base.SystemCheckError: SystemCheckError: System check identified some issues:
ERRORS:
database.LeadsStatus.company_id: (fields.E305) Reverse query name for 'LeadsStatus.company_id' clashes with reverse query name for 'LeadsStatus.companies'.
HINT: Add or change a related_name argument to the definition for 'LeadsStatus.company_id' or 'LeadsStatus.companies'.
database.Users.id: (fields.E007) Primary keys must not have null=True.
HINT: Set null=False on the field, or remove primary_key=True argument.
System check identified 2 issues (0 silenced).
This is how I've created model.
class LeadsStatus(models.Model):
id = models.IntegerField(primary_key=True, auto_created=True)
company_id = models.ForeignKey('Companies', null=False, db_index=True, on_delete=models.CASCADE)
status = models.CharField(max_length=120)
users_id = models.IntegerField()
assign_date = models.DateTimeField()
companies = models.OneToOneField('Companies', on_delete=models.CASCADE)
I believe the error might be because of the way I have created a OneToOneField. How do I solve this error. Please help me understand. Thanks

If you really need 2 foreing keys to the model Companies, then you need to set the option related_name to distinguish them.
You can change your class to, for example, this:
class LeadsStatus(models.Model):
...
company_id = models.ForeignKey(
'Companies',
null=False,
db_index=True,
on_delete=models.CASCADE,
related_name='leadsstatus_1_set')
...
companies = models.OneToOneField(
'Companies',
on_delete=models.CASCADE,
related_name='leadsstatus')
You could also set related_name on just one of these 2 fields, as long as it is different from the default value of leadsstatus_set.

Related

Having trouble wrapping my head around follower/target models in Models.py

I have just started with making a similar site to Pinterest and the site has follower/target system that I have barely any understanding of. So far, my models.py code is below:
from django.db import models
class User(models.Model):
username = models.CharField(max_length=45, null=True)
email = models.CharField(max_length=200, null=True)
password = models.CharField(max_length=200)
nickname = models.CharField(max_length=45, null=True)
target = models.ManyToManyField(self, through='Follow')
follower = models.ManyToManyField(self, through='Follow')
class Meta:
db_table = 'users'
class Follow(models.Model):
follower = models.ForeignKey(User, on_delete=models.CASCADE, related_name='targets')
target = models.ForeignKey(User, on_delete=models.CASCADE, related_name='followers')
class Meta:
db_table = 'follows'
This code was made with reference to another StackOverflow thread
Django models: database design for user and follower
However, I am having trouble understanding how using "related_name='targets' in 'follower' and "related_name='followers'" in 'target' where I can't see any 'targets'(plural) or 'followers'(plural) in other areas of models.py
Should I get rid of that related_name, since there is no such table called "followers" or "targets"? And if you spot major errors in my code or logic, can you tell me? Thanks!
Should I get rid of that related_name, since there is no such table called followers or targets.
There is never a table named followers or targets. The related_name [Django-doc] is a conceptual relation Django makes to the other model (in this case User). It means that for a User object myuser, you can access the Follow objects that refer to that user through target for example with myuser.followers.all(), so:
Follow.objects.filter(target=myuser)
is equivalent to:
myuser.followers.all()
The default of a related_name is modelname_set, so here that would be follow_set. But if you remove both related_names, then that would result in a name conflict, since one can not add two relations follow_set to the User model (and each having a different semantical value).
if you spot major errors in my code or logic, can you tell me?
The problem is that since ManyToManyFields refer to 'self' (it should be 'self' as string literal), it is ambigous what the "source" and what the target will be, furthermore Django will assume that the relation is symmetrical [Django-doc], which is not the case. You should specify what the source and target foreign keys are, you can do that with the through_fields=… parameter [Django-doc]. It furthermore is better to simply define the related_name of the ManyToManyField in reverse, to avoid duplicated logic.
from django.db import models
class User(models.Model):
username = models.CharField(max_length=45, unique=True)
email = models.CharField(max_length=200)
password = models.CharField(max_length=200)
nickname = models.CharField(max_length=45)
follows = models.ManyToManyField(
'self',
through='Follow',
symmetrical=False,
related_name='followed_by',
through_fields=('follower', 'target')
)
class Meta:
db_table = 'users'
class Follow(models.Model):
follower = models.ForeignKey(
User,
on_delete=models.CASCADE,
related_name='targets'
)
target = models.ForeignKey(
User,
on_delete=models.CASCADE,
related_name='followers'
)
class Meta:
db_table = 'follows'
Here a User object myuser can thus access myuser.follows.all() to access all the users that they follow, myuser.followed_by.all() is the set of Users that follow myuser. myuser.targets.all() is the set of Follow objects that he is following, and myuser.followers.all() is the set of Follow objects that are following that user.

creating django model for review gives this msg

When i try to create the reviews table, i get the the following error message. The models.py and error message in the terminal is mentioned below.
models.py
class reviews(models.Model):
reviewee = models.ForeignKey('Person', on_delete=models.CASCADE)
reviewer = models.ForeignKey('Person', on_delete=models.CASCADE)
review = models.TextField()
rating = models.FloatField()
class Person(models.Model):
email = models.CharField(max_length=30)
pwd = models.CharField(max_length=30)
type = models.CharField(max_length=30)
terminal output
SystemCheckError: System check identified some issues:
ERRORS:
pfapp.reviews.reviewee: (fields.E304) Reverse accessor for 'reviews.reviewee' clashes with reverse accessor for 'reviews.reviewer'.
HINT: Add or change a related_name argument to the definition for 'reviews.reviewee' or 'reviews.reviewer'.
pfapp.reviews.reviewer: (fields.E304) Reverse accessor for 'reviews.reviewer' clashes with reverse accessor for 'reviews.reviewee'.
HINT: Add or change a related_name argument to the definition for 'reviews.reviewer' or 'reviews.reviewee'.
System check identified 2 issues (0 silenced).
The logic behind my models is that on person can review another person. Also, when either reviewer or reviewee is deleted from the table, the review should also be deleted.
i hope you got my idea.
You can do and then migrate:
reviewee = models.ForeignKey('Person', on_delete=models.CASCADE)
reviewer = models.ForeignKey('Person', on_delete=models.CASCADE, related_name="reviewer", null=True)
Now, on reverse you can get reviewee from person.reviews which is by default. And, get reviewer from person.reviewer. Have a look at this SO question for greater understanding.

How to Model Peer to Peer Transactions in Django?

I'm trying to figure out the correct way to model transactions between users in an ecommerce site I'm building. I want the transaction to be available to both users in a dashboard.
It seems incorrect to have the transaction, and all its details, saved to both users objects. I think I need to create a separate model for transactions, with a unique id for each transaction. Then, in each user's object I could simply save that transaction id.
Would I then simply give each transaction two primary keys, one for the purchaser's user.id and one for the purchasee's user.id? Is this "many to many"?
Thanks for any guidance here.
Edit - Here is what I've tried:
class Transaction(models.Model):
owner = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
purchaser = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
create_time = models.DateField(auto_now=True)
item = models.ForeignKey(Item, on_delete=models.CASCADE)
However, this gives an error items.Transaction.owner: (fields.E304) Reverse accessor for 'Transaction.owner' clashes with reverse accessor for 'Transaction.purchaser'.
HINT: Add or change a related_name argument to the definition for 'Transaction.owner' or 'Transaction.purchaser'.
You should add related_name parameter for both fields each has its own name, Like :
class Transaction(models.Model):
owner = models.ForeignKey(get_user_model(), on_delete=models.CASCADE, related_name = 'transaction_owner')
purchaser = models.ForeignKey(get_user_model(), on_delete=models.CASCADE, related_name = 'transaction_purchaser')
create_time = models.DateField(auto_now=True)
item = models.ForeignKey(Item, on_delete=models.CASCADE)
More Context : Django: Why do some model fields clash with each other?

Reason for IntegrityError on Field deletion?

I have a webservice setup with Django backend and I am trying to delete entries for my Field objects. Each Field is assigned to a User and there are a number of Assessments done in the Field. The Assessments are linked to the Fields via a foreign key. Upon deletion of the Field object I want to also delete all the Assessments for that Field, but keep the User.
I played around with the on_deletion parameter and if I set it to CASCADE the Django admin page shows me all the associated Assessment objects if I try to delete the Field object. However, I am still getting the following error:
IntegrityError at /admin/dfto/field/ update or delete on table "field"
violates foreign key constraint "assessment_field_uuid_fkey" on table
"assessment" DETAIL: Key
(uuid)=(f3a52c10-33be-42f9-995d-482025cea17b) is still referenced from
table "assessment".
These are my models for Reference:
class Assessment(models.Model):
uuid = models.TextField(primary_key=True)
longitude = models.FloatField(blank=True, null=True)
latitude = models.FloatField(blank=True, null=True)
field_uuid = models.ForeignKey('Field', models.CASCADE, db_column='field_uuid',blank=True, null=True, related_name='assessments')
class Meta:
db_table = 'assessment'
class Field(models.Model):
uuid = models.TextField(primary_key=True)
name = models.CharField(max_length=50, blank=True, null=True)
country = models.CharField(max_length=50, blank=True, null=True)
user_email = models.ForeignKey('User', models.DO_NOTHING, db_column='user_email')
crop_uuid = models.ForeignKey(Crop, models.CASCADE, db_column='crop_uuid')
class Meta:
db_table = 'field'
Can someone explain to me why I am getting this error and/or provide a fix for me?
I think it's because field_uuid have argument 'models.CASCADE' so when you are deleting it, django also tries to delete any refences to this particular key, don't know how to fix it tho.

Access to fields of on reverse relation in django

I have these models:
class Task(models.Model):
user = models.ForeignKey(User)
name = models.CharField()
class Report(models.Model):
task = models.ForeignKey(
Task, blank=True, null=True, related_name='+')
status = models.CharField(max_length=32, choices=Status.CHOICES, default=Status.INCOMPLETE)
Now I want to get all Tasks and their related status.
How do I do this?
At first, '+' is not a valid related_name. It is also not very explicit.
Try replacing '+' with 'reports' instead:
# ...
class Report(models.Model):
task = models.ForeignKey(
Task,
blank=True,
null=True,
related_name='reports' # <<<
)
status = models.CharField(
max_length=32,
choices=Status.CHOICES,
default=Status.INCOMPLETE
)
Then to get all the Tasks with their related status, you can use values:
>>> Task.objects.values('name', 'report__status')
<QuerySet [{'name': 'test', 'report__status': 'OK'}, ...]>
The sign + is exactly what you don't want to have as related_name in this case. It tells Django to not create a backwards relation. Check out here. Chose another valid name or skip this argument, in which case Django will create a reverse relation by default using for the name of the backwards relation the model name lowercased and the suffix _set (see here for details).
However, in your example if you want to get all reports which are related to a task and the corresponding status you do not necessarily need backwards relationships. Try this:
reports = Report.objects.exclude(task__isnull=True).values('task__name', 'status')
Change the value of related_name to something else, like 'reports' for example:
class Report(models.Model):
task = models.ForeignKey(
Task, blank=True, null=True, related_name='reports')
status = models.CharField(max_length=32, choices=Status.CHOICES, default=Status.INCOMPLETE)
Now if you have a Task object (not queryset), you can get a queryset of it's reports using:
reports = task.reports.all()
You can use filter() on the reports if you need to.
reports = task.reports.filter(status='something')

Categories

Resources