FieldError Cannot resolve keyword 'XXXX' into field, on wrong entity - django

I don't understand this error on my model. My model (django 1.5.4):
from django.db.models import Model
from django.db import models
from django.utils.translation import ugettext_lazy as _
class ProductFactory(Model):
name = models.CharField(_(u"Name"), max_length=128)
products = models.ManyToManyField('Product', through='ProductFactoryProduct', related_name='factory')
components = models.ManyToManyField('Product', through='ProductFactoryComponent', related_name='factory')
class ProductFactoryProduct(Model):
factory = models.ForeignKey('ProductFactory')
product = models.ForeignKey('Product')
quantity = models.IntegerField(_(u"Quantity"), default=1)
class ProductFactoryComponent(Model):
factory = models.ForeignKey('ProductFactory')
product = models.ForeignKey('Product')
quantity = models.IntegerField(_(u"Quantity"), default=1)
class Product(Model):
active = models.BooleanField(_(u"Active"), default=True)
barcode = models.CharField(_(u"Barcode"), max_length=32, blank=True, null=True)
[...] # Nothing about factory
When i try to get Factory.products or Factory.components:
factory = ProductFactory.objects.get(pk=factory_id)
factory.products.all()
This error is throwed:
FieldError at /stock/factory/view/1
Cannot resolve keyword 'factory' into field. Choices are: active,
article, barcode, brand, categorys, code, comsumtion_type, id, name,
packaging, productreference, provider, providers, purchase_quantity,
quantity, quantity_with_ampute, stock_limit, stockmovement,
stockmovementproduct, work_unit
Note: active, article, barcode [...] fields are Product entity fields.
I don't understand why django is trying to use factory key on Product entity instead on ProductFactoryProduct entity. My model is wrong ? What is the problem ?
Edit: Full code: http://pastebin.com/SaMMUjd6

In class ProductFactory(Model): products and components have the same related_name (related_name='factory')
Try to change one.

Related

Exporting and Importing a foreign key field that has a many-to-many relationship in Django

I've got a complicated relationship between my Django models and I'm trying to get django-import-export to play nicely.
class Person(models.Model):
name = models.CharField(max_length=64)
class Team(models.Model):
rep = models.ManyToManyField(Person, related_name="rep")
def get_reps(self):
return "/".join(sorted([p.name for p in self.reps.all()]))
class Account(models.Model):
tid = models.IntegerField("Territory ID", primary_key=True)
name = models.CharField("Territory Name", max_length=64)
sales_team = models.ForeignKey(Team, related_name="sales_team")
I'm trying to export (and hopefully later import) the territories with the names of the reps as rendered by the get_reps method.
class TerritoryResource(resources.ModelResource):
tid = fields.Field(attribute='tid', column_name="Territory ID")
name = fields.Field(attribute='name', column_name="Territory Name")
sales_team = fields.Field(
column_name="Sales Team",
widget=widgets.ForeignKeyWidget(Team, "get_reps")
)
The export is giving me a blank field. If I don't use the widget I get the Team ID as I'd expect.
Is it possible to get my custom name in the export?
I didn't include the standard __str__ methods in the sample code, because I didn't think they were important, but I did have in my Team class definition:
def __str__(self):
return self.get_reps()
This means, had I read the documentation with a little more creativity, I would have figured out how to do this. It's deceptively simple:
class TerritoryResource(resources.ModelResource):
...
def dehydrate_sales_team(self, territory):
return str(territory.sales_team)
I could also use return territory.sales_team.get_reps() to get the same results.

How to define two Django fields unique in certain conditions

I want to make Django Model fields unique with two fields(values) in some conditions.
there's two fields: 'team', 'type'. And I want to make team manager unique
For Example:
team=1, type='manager'
team=1, type='manager'
-> Not available
team=1, type='manager'
team=1, type='member'
team=1, type='member'
team=2, type='manager'
-> Available
I think unique_together('team', 'type') won't work properly with this situation.
How can I make this with Django Model?
Here's my model below:
class myModel(models.Model):
team = models.ForeignKey('Team', on_delete=models.CASCADE)
type = models.CharField(max_length=10, default='member')
class Meta:
db_table = 'my_models'
I think, You need to use UniqueConstraint for your application which work perfect in kind of situation.
class myModel(models.Model):
team = models.ForeignKey('Team', on_delete=models.CASCADE)
type = models.CharField(max_length=10, default='member')
class Meta:
db_table = 'my_models'
constraints = [
models.UniqueConstraint(fields=['team', 'type'], name='unique_team')
]
you can also refer this link for more understanding. and let me know if following solution will work.
Given that there is a deprecation warning in the documentation (based on 3.2 docs) for unique_together, I think it's worth showing that this can be done using UniqueConstraint. I believe that the key missing ingredient from the previous answer is the use of UniqueConstraint.condition, like so:
from django.db import models
from django.db.models import Q, UniqueConstraint
class myModel(models.Model):
team = models.ForeignKey('Team', on_delete=models.CASCADE)
type = models.CharField(max_length=10, default='member')
class Meta:
db_table = 'my_models'
constraints = [
UniqueConstraint(
fields=['team', 'type'],
name='unique_team',
condition=Q(type='manager')
)
]

Put a constraint on an attribute of a related model

I have two models: Account and Transfer.
The model Account has the attribute currency (EUR, USD, JPY, etc.).
The model Transfer has two attributes account_from and account_to.
I want to add a constraint that checks that account_from uses the same currency as account_to.
I was thinking of adding such a constraint on Transfer model:
class Meta:
constraints = [
CheckConstraint(check=Q(account_from__currency=F('account_to__currency')), name='same_currency'),
]
But that doesn't work because of error
django.core.exceptions.FieldError: Joined field references are not permitted in this query
How do I do that ? Without relying on SQL. I know how to do that in SQL but I want to use the ORM. Or is it impossible to do that with Django ORM ?
Here are the two models (simplified to avoid noise):
class Tranfer(AuditedModel):
"""
The action of moving money from one account to another
"""
account_from = models.ForeignKey(Account, related_name="outgoing", on_delete=models.CASCADE)
account_to = models.ForeignKey(Account, related_name="incoming", on_delete=models.CASCADE)
class Account(AuditedModel):
"""
Recipient for money
"""
currency = models.CharField('currency', max_length=3, choices=(('EUR', 'Euro'), ('USD', 'American Dollars'), ('JPY', 'Japan Yen')))
class Meta:
constraints = [
CheckConstraint(check=Q(account_from__currency=F('account_to__currency')), name='same_currency'),
]
Follow the following steps for the solution of your problem.
The constrain section should be in the Transfer Model not in Account model.
Check constrain for any two relational model must be avoided.
The alternative for CheckConstraint() in the Constraint array of Meta section use the function clean for validation rather than constraint.
from django.db import models
from django.core.exceptions import ValidationError
class Account(models.AuditedModel):
"""
Recipient for money
"""
currency = models.CharField('currency', max_length=3, choices=(
('EUR', 'Euro'),
('USD', 'American Dollars'),
('JPY', 'Japan Yen')
))
class Transfer(models.AuditedModel):
"""
The action of moving money from one account to another
"""
account_from = models.ForeignKey(Account, related_name="outgoing", on_delete=models.CASCADE)
account_to = models.ForeignKey(Account, related_name="incoming", on_delete=models.CASCADE)
def clean(self):
if self.account_from.currency != self.account_to.currency:
raise ValidationError("Same currency required for transaction.")
return super().clean()

How to query by joining a Django Model with other, on a non unique column?

I have the following models in my models.py file in my django project
from django.contrib.auth.models import AbstractUser
from django.db import models
from django.conf import settings
class CustomUser(AbstractUser):
pass
# add additional fields in here
class PDFForm(models.Model):
pdf_type=models.IntegerField(default=0)
pdf_name=models.CharField(max_length=100,default='')
file_path=models.FileField(default='')
class FormField(models.Model):
fk_pdf_id=models.ForeignKey('PDFForm', on_delete=models.CASCADE,default=0)
field_type=models.IntegerField(default=0)
field_page_number=models.IntegerField(default=0)
field_x=models.DecimalField(max_digits=6,decimal_places=2,default=0)
field_y=models.DecimalField(max_digits=6,decimal_places=2,default=0)
field_x_increment=models.DecimalField(max_digits=6,decimal_places=2,default=0)
class Meta:
ordering= ("field_page_number", "field_type")
class UserData(models.Model):
fk_user_id=models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE,default=0)
field_type=models.IntegerField(default=0)
field_text=models.CharField(max_length=200,default='')
field_date=models.DateField()
Here is how the models are related
1) a pdfform contains a pdf form and path for it on the file system
2) A pdfform has multiple FormFields in it. Each field has attributes, and the specific one under discussion is field_type
3)The UserData model has user's data, so one User can have multiple rows in this table. This model also has the field_type column.
What I am trying to query is to find out all rows present in the Userdata Model which are present in the FormField Model ( matched with field_type) and that are of a specific PDFForm.
Given that the Many to Many relationship in django models cannot happen between no unique fields, how would one go about making a query like below
select a.*, b.* from FormField a, UserData b where b.fk_user_id=1 and a.fk_pdf_id=3 and a.field_type=b.field_type
I have been going through the documentation with a fine toothed comb, but obviously have been missing how django creates joins. what is the way to make the above sql statement happen, so I get the required dataset?
I think UserData is missing a relation to FormField, but if you had this relation you could do:
UserData.objects.filter(
fk_user_id=1, # Rename this to user, Django wilt automicly create a user_id column
form_field__in=FormField.objects.filter(
fk_pdf_id=<your pdfid> # same as fk_user_id
)
)
Edit updated models
When you use a ForeignKey you don't have to specify the _id or default=0, if you don't always want to fill the field its better to set null=True and blank=True
from django.contrib.auth.models import AbstractUser
from django.db import models
from django.conf import settings
class CustomUser(AbstractUser):
pass
# add additional fields in here
class FieldTypeMixin:
TYPE_TEXT = 10
TYPE_DATE = 20
TYPE_CHOISES = [
(TYPE_TEXT, 'Text'),
(TYPE_DATE, 'Date'),
]
field_type=models.IntegerField(default=TYPE_TEXT, choises=TYPE_CHOISES)
class PDFForm(models.Model):
pdf_type = models.IntegerField(default=0)
pdf_name = models.CharField(max_length=100,default='')
file_path = models.FileField(default='')
class FormField(models.Model, FieldTypeMixin):
pdf_form = models.ForeignKey('PDFForm', on_delete=models.CASCADE)
field_page_number = models.IntegerField(default=0)
field_x = models.DecimalField(max_digits=6,decimal_places=2,default=0)
field_y = models.DecimalField(max_digits=6,decimal_places=2,default=0)
field_x_increment = models.DecimalField(max_digits=6,decimal_places=2,default=0)
class Meta:
ordering = ("field_page_number", "field_type")
class SubmittedForm(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, models.CASCADE)
pdf_form = models.ForeignKey(PDFForm, models.CASCADE)
class SubmittedFormField(models.Model, FieldTypeMixin):
submitted_form = models.ForeignKey(SubmittedForm, models.CASCADE)
form_field = models.ForeignKey(FormField, models.CASCADE, related_name='fields')
field_text = models.CharField(max_length=200,default='')
field_date = models.DateField()
class Meta:
unique_together = [
['submitted_form', 'form_field']
]

How to make a query on related_name field?

I have to models connected by a ForeignKey
class User(AbstractUser):
...
and
class PrivateMessage(models.Model):
user_from = models.ForeignKey(
User,
verbose_name=u'From',
related_name='sent_messages',
)
user_to = models.ForeignKey(
User,
verbose_name=u'To',
related_name='received_messages',
)
Is there any way to get all the addresses for a particular user. For example, if
u = User.objects.get(id=1)
messages = PrivateMessage.objects.filter(user_from=u)
for m in messages:
users.add(m.user_to)
How to obtain a list of users that appear in user_to for these messages using only Django ORM methods?
I think a better idea would be to define ManyToManyField on the User model:
class User(AbstractUser):
#...
receivers = models.ManyToManyField('self', through='Message',
symmetrical=False, related_name="senders")
class Message(models.Model):
user_from = models.ForeignKey(MyUser, related_name='messages_from')
user_to = models.ForeignKey(MyUser, related_name='messages_to')
message = models.CharField(max_length=100, default="")
#...
Then to retrieve users list on the other end you simply do:
User.objects.get(id=1).receivers.all() # who I sent the message to
User.objects.get(id=1).senders.all() # who sent me a message
This way you have a nice clear API.
Finally, I ended up writing three queries:
users_from = set(PrivateMessage.objects.filter(
user_to=self.request.user,
).values_list(
'user_from__pk',
flat=True,
))
users_to = set(PrivateMessage.objects.filter(
user_from=self.request.user,
).values_list(
'user_to__pk',
flat=True,
))
interlocutors = User.objects.filter(pk__in=users_from.union(users_to))
I saw this docs
Maybe you can try:
u = User.objects.get(id=1)
users = User.objects.filter(received_messages__user_from=u).distinct()
related_name field makes our queries especially the ones using foreign key (on to many relation) easier, shorter and cleaner.
Let say we have 2 models classes Library and Book.
class Library(Models.model):
name = models.CharField(max_length = 100)
`class Book(Models.model):
title = models.CharField(max_length = 100)
library = models.ForeignKey(Library,
on_delete = models.CASCADE,
related_name = 'books')`
Here we have a one to many relation from Library to Book using foriegn key.
And in my django shell. I can create a new Library and a book related to that library in the following manner.
`from <app_name>.models import *`
`library = Library.objects.create(name = 'Big Library')`
`Book.objects.create(title = 'Awesome book', library = library`
Now I can query the book of the library using related name of model Book class:
`library.books.all()`
rather than using the starting the query from Book model as:
Book.objects.filter(library = library)