I know I can easily grab the latest entered object, but assuming an update is made to an object in the middle of the pack lets say object 50 of 100, is there a way to query the database to grab that latest update? I.e. number 50, since it was the latest to be updated as opposed to entered into the db?
I searched online and couldn't find anybody trying to accomplish this.
Thanks,
If your model have a DateTimeField with auto_now=True, you can use QuerySet.latest method with that field name specified.
For example, assuming that Model has a field DateTimeField updated_at with auto_now set:
last = Model.objects.lastest('updated_at')
Related
I am working on converting some relatively complex SQL into something that Django can play with. I am trying not to just use the raw SQL, since I think playing with the standard Django toolkit will help me learn more about Django.
I have already managed to break up parts of the sql into chunks, and am tackling them piecemeal to make things a little easier.
Here is the SQL in question:
SELECT i.year, i.brand, i.desc, i.colour, i.size, i.mpn, i.url,
COALESCE(DATE_FORMAT(i_eta.eta, '%M %Y'),'Unknown')
as eta
FROM i
JOIN i_eta ON i_eta.mpn = i.mpn
WHERE category LIKE 'kids'
ORDER BY i.brand, i.desc, i.colour, FIELD(size, 'xxl','xl','l','ml','m','s','xs','xxs') DESC, size+0, size
Here is what I have (trying to convert line by line):
(grabbed automatically when performing filters)
(have to figure out django doc on coalesce for syntax)
db alias haven't been able to find yet - it is crucial since there is a db view that requires it
already included in the original q
.select_related?
.filter(category="kids")
.objects.order_by('brand','desc','colour') - don't know how to deal with SQL FIELDS
Any advice would be appreciated!
Here's how I would structure this.
First, I'm assuming your models for i and i_eta look something like this:
class I(models.Model):
mpn = models.CharField(max_length=30, primary_key=True)
year = models.CharField(max_length=30)
brand = models.CharField(max_length=30)
desc = models.CharField(max_length=100)
colour = models.CharField(max_length=30)
size = models.CharField(max_length=3)
class IEta(models.Model):
i = models.ForeignKey(I, on_delete=models.CASCADE)
eta = models.DateField()
General thoughts:
To write the coalesce in Django: I would not replace nulls with "Unknown" in the ORM. This is a presentation-layer concern: it should be dealt with in a template.
For date formatting, you can do date formatting in Python.
Not sure what a DB alias is.
For using multiple tables together, you can use either select_related(), prefetch_related(), or do nothing.
select_related() will perform a join.
prefect_related() will get the foreign key ID's from the first queryset, then generate a query like SELECT * FROM table WHERE id in (12, 13, 14).
Doing nothing will work automatically, but has the disadvantage of the SELECT N+1 problem.
I generally prefer prefetch_related().
For customizing the sort order of the size field, you have three options. My preference would be option 1, but any of the three will work.
Denormalize the sort criteria. Add a new field called size_numeric. Override the save() method to populate this field when saving new instances, giving xxl the value 1, xl the value 2, etc.
Sort in Python. Essentially, you use Python's built-in sorting methods to do the sort, rather than sorting it in the database. This doesn't work well if you have thousands of results.
Invoke the MySQL function. Essentially, using annotate(), you add the output of a function to the queryset. order_by() can sort by that function.
I have a model where I store the recurring sessions on my gym.
DAYS_OF_WEEK = (
(0, _("Monday")),
(1, _("Tuesday")),
(2, _("Wednesday")),
(3, _("Thursday")),
(4, _("Friday")),
(5, _("Saturday")),
(6, _("Sunday")),
)
class RecurringSession(models.Model):
session = models.ForeignKey(SessionType, db_index=True, on_delete=models.CASCADE)
dayofweek = models.PositiveSmallIntegerField(choices=DAYS_OF_WEEK)
time = models.TimeField()
However some classes happen more than once a week. Whats the best way to store multiple values (between 1 to 7) on that modelfield?
I'm using Django Mysql 8.0, and from what I understand it supports JSON field but from the django docs it seems that is only supported by Postgres so far.
Is there a specific django way to do this? Maybe storing a charfield with comma-separated values?
I wont need to search by that field.
Every week, there will be a cronjob that will read this model and create an instance of each session on another model.
(I need each session as an instance for customization: teacher substitution, session roster, session status - i may cancel a single session on a bank holiday or for another reason).
So this "RecurringSessions" will be where I store the session information that will be generated every week.
The way that I wrote at first there will be an model instance for each day of the week of the same session, but I want to group them in the same instance because I think its looks nicer and may make it easier to set the teacher in bulk.
Alternatively, I could store a json with a dict for multiple day/time values for each session, however that would make it a little bit more difficult to make sure that if the cronjob is run twice the class doesnt get duplicated.
Now, to avoid that, I have a UniqueConstraint in my schedule model with fields "day", "time" and "room"
Using Django 3.0.6, Python 3.8.2, and MySQL 8.0.20.
thanks
You're attempting to do a many-to-one relationship, so you'll either have to use this method docs.djangoproject.com/en/3.0/topics/db/examples/many_to_one, or if you want to avoid creating a database table and utilize Django's choice field, you can use this extension.
Since there are seven fixed days in a week, I'll prefer the second method instead of creating a DB table, and unnecessary DB queries.
It's hard to say the best structure without knowing what you're ultimately going to do with the model, however, I don't see why you couldn't have a single Session model that covers everything - like so:
class Session(models.Model):
TYPE_CHOICES = (('C','Cardio'), #...and so on
DAY_CHOICES = ((1,'Monday'), #...and so forth
type = models.CharField(max_length=10, choices=TYPE_CHOICES)
day = models.PositiveSmallIntegerField(choices=DAY_CHOICES)
time = models.TimeField()
You could find the recurring sessions by counting the occurrences of a session once you've applied a filter to type or another field. That would keep your model structure concise and give you enough information in a single place to do filtering, annotation, etc. as required.
So I'm a beginner in Django, and recently came up with a question, regarding datetime.
So I'm trying to make a blog-like page. And among the input fields, including title and contents, I want a datetime field as well. However, there is an additional feature that I want to create, which is -- if the user clicks a checkbox right next to the datetime input field, the datetime will automatically change into the CURRENT date and time. So the input field is replaced with the current date and time.
I have no idea on how to create the feature.
I would very much appreciate your help :)
It will be better if you make this behavior to be set automatically to the time of creating the post for the first time, it will not be triggered if you modify the post:
created_at = models.DateTimeField(auto_now_add=True)
If you want to set it to the current time when you modify the post:
modified_at = models.DateTimeField(auto_now=True)
I am a newbie with Django trying to create a dashboard application reporting on some key milestone dates. I want to be able to track how the key dates are changing. For example:If the kick off date has been changed 5 times I want to be able to report 1. the first date entered, 2. Current date, 3. The date before the last update.
Thank you
Your question is not clear. But for the logic you have asked one thing we can do is to make a model in which the edited dates and user will be fields. Use user as foreign key of your User model. I will just give an example model.
class Dates(models.Model):
event = models.ForeignKey(Event)
date = models.DateField()
This is a very basic method which i am saying. This is a bit complex and you will have to check if the field has changed five times and all.
For a better answer please make the question clear.
Bit of a random question but ill try my best to describe what im trying to do. I am building a app to manage a set of physical assets which get loaned out.
To return an asset the user visits /return/1/ which clears the name of the user, date borrowed, date returned etc
view.py
def returnlaptop(request, laptop_pk):
Laptops.objects.filter(pk=laptop_pk).update(laptop_status='In')
Laptops.objects.filter(pk=laptop_pk).update(user='')
Laptops.objects.filter(pk=laptop_pk).update(borrowed_date='')
Laptops.objects.filter(pk=laptop_pk).update(return_date='')
return HttpResponseRedirect('/')
This works well except for when i try and update the values in the models.datefield
[u"' ' value has an invalid date format. It must be in YYYY-MM-DD format."]
Is there anyway around this? or am I going about this the completely wrong way?
Cheers
Xcom
I'm not 100% sure but I think that hits the database 4 times...
The first issue is that update is meant for use on a queryset. You are filtering on the primary key so you are only getting 1 object back. Which means that you should use get instead like this
laptop = Laptops.objects.get(pk=laptop_pk)
and now you can use that to properly fetch the object from the database, modify it, and save it like so
laptop = Laptops.objects.get(pk=laptop_pk)
laptop.laptop_status = 'In'
laptop.user = ''
...
laptop.save()
which would only hit the database 1 time.
The final issue is that you are attempting to set a date to an empty string. That won't work because it is expecting a date object. One thing you can do is modify your model so that the dates can be blank and so that the database accepts null values.
class Laptops(models.Model):
...
borrowed_date = models.DateField(null=True, blank=True)
return_date = models.DateField(null=True, blank=True)
The other thing you can do is use the minimum date can be accessed with timezone.datetime.min