Django model allow only once in many - django

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.

Related

Slow loading Django Admin change/add

The Loading time is too much for this particular model in admin panel.I know it is because I have too many values in Foreign Fields (field with 20k+ records each) which takes too much time to load on client side. Is there a way to optimise this? below is my code and screenshot of loadtime,
Loading Time
Models:
class Alert(BaseModelCompleteUserTimestamps):
type = models.ForeignKey(to=AlertType, on_delete=models.CASCADE, verbose_name="Type")
device = models.ForeignKey(Device, on_delete=models.CASCADE, related_name="alert_device")
device_event = models.ForeignKey("dm_detection.VIDSDetection",
on_delete=models.CASCADE, null=True, blank=True, related_name="device_event")
anpr_event = models.ForeignKey("dm_detection.VSDSDetection",
on_delete=models.CASCADE, null=True, blank=True, related_name="anpr_event")
ecb_event = models.ForeignKey("dm_detection.ECBDetection",
on_delete=models.CASCADE, null=True, blank=True, related_name="ecb_event")
hr_only = models.IntegerField(null=True, blank=True)
# acknowledged
is_acknowledged = models.BooleanField(default=False, verbose_name="Acknowledged")
acknowledged_at = models.DateTimeField(blank=True, null=True)
acknowledged_by = models.ForeignKey(to=User, on_delete=models.CASCADE, null=True, blank=True,
related_name="alert_acknowledged_by")
# resolved
is_resolved = models.BooleanField(default=False, verbose_name="Resolved")
resolved_at = models.DateTimeField(blank=True, null=True)
resolved_by = models.ForeignKey(to=User, on_delete=models.CASCADE, null=True, blank=True,
status = models.ForeignKey(to=TicketStatus, on_delete=models.DO_NOTHING, default=1)
Admin.py
#admin.register(Alert)
class AlertModelAdmin(BaseModelCompleteUserTimestampsAdmin):
form = AlertEditForm
fields = ('type',
'device',
'device_event',
'status', 'hr_only',
'is_acknowledged', 'acknowledged_at', 'acknowledged_by',
'is_resolved', 'resolved_at', 'resolved_by', 'anpr_event',
'created_at',
'updated_at', 'OD_vehicle_number'
)
Forms.py
class AlertEditForm(forms.ModelForm):
status = forms.ModelChoiceField(queryset=TicketStatus.objects.filter(is_for_alert=True))
device_event = forms.ModelChoiceField(queryset=VIDSDetection.objects.all())
anpr_event = forms.ModelChoiceField(queryset=VSDSDetection.objects.all())
acknowledged_by = forms.ModelChoiceField(queryset=User.objects.all())
resolved_by = forms.ModelChoiceField(queryset=User.objects.all())
class Meta:
model = Alert
fields = '__all__'

How to sort using foreign key field in django and avoid multiple results of same row

I want to sort Groups with their 'is_favorite' boolean field from model GroupUser. I have two models GroupUser where there is a foreign key to Group model, now when I query Group.objects.filter(is_active=True).order_by('groupuser__group_id__is_favorite')
I get groups multiple times. I tried to user distict() on final queryset still no luck. Pls suggest any other way or possible solution. TIA.
class Group(models.Model):
group_name = models.CharField(
max_length=250)
context_type = models.ForeignKey(
"contenttypes.ContentType",
on_delete=models.DO_NOTHING,
blank=True,
null=True,
related_name="content_type")
context = models.IntegerField(
blank=True,
null=True)
privacy_type = models.ForeignKey(
"commans.PrivacyType",
on_delete=models.DO_NOTHING,
blank=True,
null=True,
related_name="group_privacy_id")
is_active = models.BooleanField(
default=True,
help_text="Is Group Active")
class GroupUser(models.Model):
group = models.ForeignKey(
"Group",
on_delete=models.DO_NOTHING,
blank=True,
null=True,
related_name="groupuser_group_id")
user=models.ForeignKey(
"auth_module.User",
on_delete=models.DO_NOTHING,
blank=True,
null=True)
is_favorite = models.BooleanField(
default=False,
blank=True,
null=True)
```
We can use an annotation to count the number of favourites each Group has. Then we can use this annotation to order by
from django.db.models import Sum
Group.objects.filter(
is_active=True
).annotate(
total_favorites=Sum('groupuser_group_id__is_favorite')
).order_by(
'-total_favorites'
)

Search Two Django Tables once within singel query

I am really confusing about Django joins. I want to search a keyword in two tables with a single query. can anyone help me?
the app model structure like this
class Events(models.Model):
event_type = models.CharField(_("Event Type"), max_length=5, choices=event_type_choices)
webinar_title = models.CharField(_("Webinar Title"), max_length=50, blank=True, null=True)
event_name = models.CharField(_("Event Name"), max_length=50, blank=True, null=True)
banner_title = models.CharField(_("Banner Title"), max_length=50, blank=True, null=True)
added_by = models.ForeignKey(User, null=True, blank=True, on_delete=models.SET_NULL)
status = models.BooleanField(_("Event Status"), default=True)
class Meta:
verbose_name = _('Event')
db_table = 'events'
app_label = 'events'
class WebinarSpeakers(models.Model):
event = models.ForeignKey(Events, on_delete=models.CASCADE, null=True)
speaker = models.CharField(_("Speaker Name"), max_length=100, null=True, blank=True)
job_title = models.CharField(_("Job Title"), max_length=255)
place_of_work = models.CharField(_("Place of Work"), max_length=100)
credentials = models.TextField(_("Credentials"), null=True, blank=True)
image = models.ImageField(_("Speaker Image"), upload_to=speaker_file_name, null=True, blank=True)
class Meta:
verbose_name = _('Event Webinar Speakers')
db_table = 'webinar_speakers'
app_label = 'events'
Now I want to search a keyword in webinar_title, evetn_name, banner_title, speaker, 'job_title` with a single query. how to do it in Django joins. I read the select_related document. it confusing me.
WebinarSpeakers.objects.filter(event__webinar_title="something", event__event_name="something", event__banner_title="somethng", speaker="something",job_title="something")

under same username I can not post?

I am using Django 2.07. In my application after posting the first post, the second post it is not taking a post under the same username (I'm using Django all-auth). At Django admin, it shows me "this username already exits."
this is my profile model:
class Profile(models.Model):
PUBLIC = 'Public'
PRIVATE = 'Private'
INITIATIVE ='Initiative'
PRIVATE_STARTUP = 'Private and Startup'
INITIAL_KEYWORD = (
(PUBLIC, 'Public'),
(PRIVATE, 'Private'),
(INITIATIVE, 'Initiative'),
(PRIVATE_STARTUP, 'Private and Startup'),
)
Type_of_account = models. NullBooleanField('Personal account',
help_text="by default this is Business account")
user_photo = models.ImageField(upload_to='user_image', blank=True)
user = models.OneToOneField(User, on_delete=models.CASCADE, default=1)
occupation = models.CharField(max_length=400, null=False)
name = models.CharField(max_length=200, null=False, blank=False, default=None)
title = models.CharField(max_length=100, null=True, blank=True)
url = models.URLField(max_length=200, null=True, blank=True)
additional_url = models.URLField(max_length=200, null=True, blank=True )
Headquarter = models.CharField(max_length=1000, null=True, blank=True)
stock_market = models.CharField(max_length=200, null=True, blank=True)
established = models.DateField(auto_now=False, auto_now_add=False, default=None)
investors = RichTextField(null=True, blank=True)
about_details = RichTextField(null=False, blank=False, default=None)
Type_of_company = models.CharField(
max_length=20,
null=True,
blank=True,
choices=INITIAL_KEYWORD,
default=PRIVATE_STARTUP)
This is my main-model.
class MainModel(models.Model):
I_THINK = 'I think'
GOOD_PART = 'Good part'
BAD_PART ='Bad part'
PROTOTYPE = 'Prototype'
FEEDBACK = 'Feedback'
INFO = 'Info'
REVIEW = 'Review'
ASK = 'Ask'
FINACIAL_MARKET = 'Financial market'
INITIAL_KEYWORD_FOR_THOUGHTS = (
(I_THINK, 'I THINK'),
(FEEDBACK, 'FEEDBACK'),
(GOOD_PART, 'GOOD PART'),
(BAD_PART, 'BAD PART'),
(PROTOTYPE, 'PROTOTYPE'),
(INFO, 'INFO'),
(REVIEW, 'REVIEW'),
(ASK, 'ASK'),
(FINACIAL_MARKET, 'FINANCIAL MARKET')
)
user = models.OneToOneField(User, on_delete=models.CASCADE, default=None)
pub_time = models.DateTimeField('Publish time', auto_now=True)
topic = models.CharField(max_length=2000, null=True, blank=True)
##
micro_thought = models.CharField(max_length=200, null=True, blank=True)
Initial_keyword_for_thoughts = models.CharField(
max_length=300,
null=True,
blank=True,
choices=INITIAL_KEYWORD_FOR_THOUGHTS,
default=I_THINK
)
What kind of changes I have to make at main-models user field?
how I can solve this problem?
Thank you for your help.
You are using OneToOne field to relate user to Post. Using OnetoOne field a user can have atmost one post. That is the issue. Change it to ForeignKey relation.
user = models.ForeignKey(User, on_delete=models.CASCADE, default=None)

Is the word start a usable field name in a Django model?

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.