I'm struggling with combination of AutoSlugField (from django-extensions) and ModelTranslation.
class Article(models.Model):
title = models.CharField(max_length=255, default="")
slug = AutoSlugField(
populate_from=[
"title",
],
overwrite=True,
)
Make perfect sense without model translation. Unfortunately, if title and slug fields are translatable it does not work out of the box.
The migration file created by ModelTranslation contains description for AutoSlugField:
migrations.AlterField(
model_name="article",
name="slug_de",
field=django_extensions.db.fields.AutoSlugField(
blank=True, editable=False, null=True, populate_from=["title"]
),
),
migrations.AlterField(
model_name="article",
name="slug_en",
field=django_extensions.db.fields.AutoSlugField(
blank=True, editable=False, null=True, populate_from=["title"]
),
),
But slug_en should be based on title_en and slug_de should be based on title_de. Is it possible to enforce such behavior?
Related
When accessing my ExternalRecord model via the django admin screen, or by querying ExternalRecord.objects.all(), I receive the error: psycopg2.errors.UndefinedColumn: column integrations_externalrecord.oppcontact_id does not exist
I am building an integration functionality, and we have a junction table that houses an external id and the instance in our database that corresponds to this external id, set up like so:
class ExternalRecord(UUIDPrimaryKey, CreatedModifiedMixin, models.Model):
integration = models.ForeignKey(
to=Integration,
related_name='external_records',
on_delete=models.CASCADE
)
emailuser = models.ForeignKey(
"accounts.EmailUser",
related_name='external_records',
null=True,
blank=True,
on_delete=models.CASCADE
)
institution = models.ForeignKey(
"institutions.Institution",
related_name='external_records',
null=True,
blank=True,
on_delete=models.CASCADE
)
oppcontact = models.ForeignKey(
"opp_contacts.OppContact",
related_name='external_records',
null=True,
blank=True,
on_delete=models.CASCADE
)
external_record_id = models.CharField(
max_length=1000
)
and so on...
When I view the OppContact model either by viewing in the django admin screen or with OppContact.objects.all(), I see that the model has a field for "id". When I rollback to the migration before applying the oppcontact field, everything returns to work as normal, meaning I can query/view ExternalRecords without getting an error.
This is my OppContact model:
class OppContact(UUIDPrimaryKey):
company = models.ForeignKey(
"accounts.Company",
on_delete=models.CASCADE,
blank=True,
null=True
)
first_name = models.CharField(
max_length=100
)
last_name = models.CharField(
max_length=100
)...
And this is another model to which my ExternalRecord can be linked, Institution:
class Institution(UUIDPrimaryKey, CreatedModifiedMixin, models.Model):
company = models.ForeignKey(
"accounts.Company",
related_name='institutions',
null=False,
blank=False,
on_delete=models.CASCADE,
)
owner = models.ForeignKey(
"accounts.EmailUser",
related_name='institutions',
null=True,
blank=True,
on_delete=models.CASCADE,
)
name = models.CharField(max_length=100, null=False, blank=False)....
The only difference I see between the models is the OppContact doesn't have the CreatedModifiedMixin or models.Model, but I thought UUIDPrimaryKey extended models.Model, so I didn't think it mattered.
I have been stuck on this for several days, so any pointers in the right direction would be helpful (: Thank you all!
For all those following along at home, the issue was actually with a constraint I added to the ExternalRecord model, which caused the migration to fail, which is why the column wasn't found.
Please excuse the title but I'm not sure howto put this into words.
I have a model "card" and a model "computer":
class card(models.Model):
name=models.CharField(
verbose_name = 'Name',
max_length=50,
null=True,
blank=True,
)
serial=models.CharField(
verbose_name = 'Serial',
max_length=50,
null=True,
blank=True,
)
class computer(models.Model):
name=models.CharField(
verbose_name = 'Name',
max_length=50,
null=True,
blank=True,
)
slot1 = models.OneToOneField(
'card',
related_name='cardslot1',
on_delete=models.SET_NULL,
null=True,
blank=True,
verbose_name = 'Slot 1',
)
slot2 = models.OneToOneField(
'card',
related_name='cardslot2',
on_delete=models.SET_NULL,
null=True,
blank=True,
verbose_name = 'Slot 2',
)
(Of course that this computer model is invalid)
The cards are unique and should only be allowed to be used in one slot - of any computer. What's the best way to achieve this? I was thinking about a in-between table, something like
card n-1 cardcomputer n-1 computer
but I'm hoping there's a better way I'm not seeing right now.
Thanks
Use the constraints meta option for your model.
from django.db import models
from django.db.models import CheckConstraint, Q
class computer(models.Model)
name=models.CharField(
verbose_name = 'Name',
max_length=50,
null=True,
blank=True,
)
slot1 = models.OneToOneField(
'card',
related_name='cardslot1',
on_delete=models.SET_NULL,
null=True,
blank=True,
verbose_name = 'Slot 1',
)
slot2 = models.OneToOneField(
'card',
related_name='cardslot2',
on_delete=models.SET_NULL,
null=True,
blank=True,
verbose_name = 'Slot 2',
)
class Meta:
constraints = [
CheckConstraint(
check = ~Q(slot1=slot2),
name = 'unique_slot',
),
]
Yagus answer is correct, but here's a pure model alternative.
class Card(models.Model):
name = models.CharField(
verbose_name='Name',
max_length=50,
null=True,
blank=True,
)
serial = models.CharField(
verbose_name='Serial',
max_length=50,
null=True,
blank=True,
)
class Slot(models.Model):
card = models.OneToOneField(Card,
on_delete=models.SET_NULL,
null=True,
blank=True
)
computer = models.ForeignKey('Computer',
on_delete=models.CASCADE,
related_name='slots'
)
class Computer(models.Model):
name = models.CharField(
verbose_name='Name',
max_length=50,
null=True,
blank=True,
)
This way you have flexibility to add/change slots per computer in the admin panel and things are imho more readable than the constraints.
You can still access Computer.slots thanks to the related name.
I am trying to create a custom Django Admin Site for new staff members that lets a staff member edit their User first_name/last_name + get presented a list of multiple choice questions with radio select for the answer choices. The questions need to be a predefined queryset (e.g. last 5 multiple choice questions by date_created), whether a M2M entries exists already or not.
models.py
class User(models.Model):
id = models.UUIDField(
primary_key=True,
default=uuid4,
unique=True,
)
first_name = models.CharField(
max_length=100,
blank=True,
null=True,
default=None,
)
last_name = models.CharField(
max_length=100,
blank=True,
null=True,
default=None,
)
class Questions(models.Model):
id = models.UUIDField(
primary_key=True,
default=uuid4,
unique=True,
)
question_text = models.CharField(
max_length=160,
blank=True,
null=True,
default=None,
)
date_created = models.DateTimeField(
auto_now_add=True
)
users = models.ManyToManyField(
Users,
through=Questions2Users,
through_fields=('questions', 'users')
)
class AnswerChoices(models.Model):
id = models.UUIDField(
primary_key=True,
default=uuid4,
unique=True,
)
choices_text = models.CharField(
max_length=160,
blank=True,
null=True,
default=None,
)
questions = models.ForeignKey(
Questions,
related_name='questions',
on_delete=models.CASCADE,
)
class Questions2Users(models.Model):
questions = models.ForeignKey(
Questions,
on_delete=models.CASCADE
)
users = models.ForeignKey(
Users,
null=True,
blank=True,
on_delete=models.CASCADE,
)
answerchoices = models.ForeignKey(
AnswerChoices,
on_delete=models.CASCADE
)
admin.py
from django.contrib import admin
from .models import (
User,
Questions,
Answers,
Questions2Users,
)
class Questions2UsersInline(admin.TabularInline):
model = Questions2Users
class UserAdminSite(admin.ModelAdmin):
class Meta:
model = User
inlines = [
Questions2UsersInline
]
admin.site.register(User, UserAdminSite)
I have identified it as a user model admin page with an inline for the M2M model. How would I display the questions queryset all at once with question_text and choice_text?
Assuming a model that has translated fields like below, how can we query these with django-graphene?
from parler.models import TranslatableModel, TranslatedFields
class Article(TranslatableModel):
#regular fields
publishing_date = models.DateTimeField(_('publishing date'),
default=now)
# translated fields
translations = TranslatedFields(
title=models.CharField(_('title'), max_length=234),
slug=models.SlugField(
verbose_name=_('slug'),
max_length=255,
db_index=True,
blank=True,
),
meta_title=models.CharField(
max_length=255, verbose_name=_('meta title'),
blank=True, default=''),
meta_description=models.TextField(
verbose_name=_('meta description'), blank=True, default=''),
meta_keywords=models.TextField(
verbose_name=_('meta keywords'), blank=True, default=''),
)
For registering "unknown" fields I do something like:
#convert_django_field.register(GeopositionField)
def convert_geofield_to_string(field, registry=None):
return graphene.String(description=field.help_text, required=not field.null)
... but this won't work here. Any ideas?
I have a model called Order with a datetime field called start. I can read and write from/to that field no problem.
However, I just created a ModelForm and specified start as one of the fields=() in Meta and I get:
Unknown field(s) (start) specified for Order
I've made sure it is not a typo by copying and pasting the field name. If I remove that field, it works.
Here is the exact ModelForm
class OrderForm(ModelForm):
class Meta:
model = Order
fields = ('details', 'start', 'quantity', 'total')
EDIT added more details:
I tried using exclude = () to exclude all fields except those I need, and start does not appear in the form even though I don't exclude it.
Here is the model:
class Order(MyModel):
user = models.ForeignKey(User, )
invoice = models.ForeignKey(Invoice, )
unit_price = models.DecimalField(max_digits=6, decimal_places=2, blank=True, null=True, )
subtotal = models.DecimalField(max_digits=6, decimal_places=2, blank=True, null =True, )
tax = models.DecimalField(max_digits=6, decimal_places=2, blank=True, null=True, )
misc = models.DecimalField(max_digits=5, decimal_places=2, blank=True, null=True, )
total = models.DecimalField(max_digits=6, decimal_places=2, blank=True, null=True, )
start = models.DateTimeField(auto_now_add=True, blank=True, null=True, )
end = models.DateTimeField(editable=True, blank=True, null=True, )
duration = models.PositiveSmallIntegerField(blank=True, null=True, )
quantity = models.PositiveSmallIntegerField(blank=True, null=True, )
notes = models.CharField(max_length=256, blank=True, null=True, )
details = models.CharField(max_length=64, blank=True, null=True, )
configured = models.BooleanField(default=False, )
Remove:
auto_now_add=True
Model field reference | Django documentation | Django :
As currently implemented, setting auto_now or auto_now_add to True
will cause the field to have editable=False and blank=True set.
I removed the auto_now_add=True and the problem is solved.
Thanks for everyone's help.
Maybe you have editable=False defined for the start field?
According to documentation:
If False, the field will not be displayed in the admin or any other ModelForm. Default is True.