Implement items ordering in Django - python

Suppose, I want to build a simple TODO-app. I want to make it possible to create todo-items, and also it should be possible to rearrange items manually.
I made following model:
class Item(models.Model):
title = models.CharField(max_length=500)
Now, I need to add a special field, let's call it order, to keep custom ordering. It should be unique, and it should be greater for any new record, so I tried to make an AutoField.
class Item(models.Model):
title = models.CharField(max_length=500)
order = models.AutoField(primary_key=False)
But it turned out that Django doesn't support several auto fields for a single model.
I guess, it should be possible to write custom raw SQL code and use Postgres sequences directly, but it would look really ugly, and I don't want to write DB-specific code for such simple functionality.
So, here is a question: what is a common way to implement items ordering in Django? It sounds like a very common requirement, and, I think, it should be a simple way to do this.

As it turns out there is no straightforward way to implement this in Django. There are packages which help you, like this one
But I would recommend just look at their model implementation and fit your needs. models.py

You could use Item.objects.count() to automatically increment your field. Plug it in the save() method of your model so that your field is calculated each time you create an instance.

Related

How to check containment in a django arrayfield?

I am working with django models in Python where one of a model's fields is a ArrayField of id's, and, given a specific instance of a model with an ArrayField as a field, I want to check if a given id is in that instance's ArrayField. I have tried doing x in self.exampleArrayField but I get Value 'self.exampleArrayField' doesn't support membership test I have also tried x in list(self.exampleArrayField) but I have no idea if this even works (my editor, vscode, doesn't throw an error, but this is Python I'm working in). Is there a good way to do what I am trying to do?
You want to use ORM methods to achieve this.
For an example, check out the documentation on ArrayFields
We have this model
from django.contrib.postgres.fields import ArrayField
from django.db import models
class Post(models.Model):
name = models.CharField(max_length=200)
tags = ArrayField(models.CharField(max_length=200), blank=True)
def __str__(self):
return self.name
To find posts that are tagged as "django"
>>> Post.objects.filter(tags__contains=['django'])
<QuerySet [<Post: First post>, <Post: Third post>]>
Here tags__contains expands to a special filter that actually queries within the array using PostgreSQL features.
Alternatively you can use the under-documented to_python method.
Which for your example would be:
x in self.exampleArrayField.to_python()
However, take a hard look at your code and consider if this is really necessary. If you are looping over a bunch of Python objects and calling this method, you are losing 100% of the performance benefits of Postgres operating on the arrays using the ORM.

What is the best way to implement persistent data model in Django?

What I need is basically a database model with version control. So that every time a record is modified/deleted, the data isn't lost, and the change can be undone.
I've been trying to implement it myself with something like this:
from django.db import models
class AbstractPersistentModel(models.Model):
time_created = models.DateTimeField(auto_now_add=True)
time_changed = models.DateTimeField(null=True, default=None)
time_deleted = models.DateTimeField(null=True, default=None)
class Meta:
abstract = True
Then every model would inherit from AbstractPersistentModel.
Problem is, if I override save() and delete() to make sure they don't actually touch the existing data, I'll still be left with the original object, and not the new version.
After trying to come up with a clean, safe and easy-to-use solution for some hours, I gave up.
Is there some way to implement this functionality that isn't overwhelming?
It seems common enough problem that I thought it would be built into Django itself, or at least there'd be a well documented package for this, but I couldn't find any.
When I hear version control for models and Django, I immediately think of django-reversion.
Then, if you want to access the versions of an instance, and not the actual instance, simply use the Version model.
from reversion.models import Version
versions = Version.objects.get_for_object(instance)
I feel you can work around your issue not by modifying your models but by modifying the logic that access them.
So, you could have two models for your same object: one that can be your staging area, in which you store values as the ones you mention, such as time_created, time_modified, and modifying_user, or others. From there, in the code for your views you go through that table and select the records you want/need according to your design and store in your definitive table.

DJANGO: How to query multiple tables, equal model without looping

I'm looking for a nice way to query(DJANGO) temporal data, which is stored in different tables, but share the same model. Here's an example data model:
class myModel(models.Model):
x = models.FloatField()
class Meta:
db_table = "24-01-2017"
Now, I could of course loop over the different days, changing _meta.db_table for every iteration, but there should be a way to do this in a single query in DJANGO. This doesn't seem to be it, as DJANGO develops this may be outdated and I don't see anything related in the documentation.
How to handle this neatly?
Thanks in advance!
Edit 1
Hm, probably I'm just looking for a way to perform a outer join... But I can't find any implementation for this.

Given Products, each with multiple Versions, what is the preferred/best way to support custom attributes at the Product/Version level in my Django app

I'm building my first Django app to manage multiple SaaS products.
This entails storing custom attributes for each Version of each Product.
For example, a new version of a Product is released that includes new configuration options that the earlier versions of the Product do not support.
I need to be able to keep track of those new values for each instance of the new Version.
I'm thinking I want the Admins to be able to add "custom fields" at the Product level by Version.
Looking for suggestions as to the best approach.
Thanks.
The common way of tracking model versions is to use django-reversion.
It sounds like each instance needs its own custom attributes. That means that changing the Models relating to Product and Version need not occur. This is good, because models can only change with the code (unless you get into dynamically generating Models which is usually not a good idea).
So, you need to be able to model attributes for each Product instance, regardless of Version. This should be a simple data modelling exercise, not necessarily related to Django.
A Product has a set of fields
A Product has a Version
A Product has a set of Attributes
This is quite easily modelled, depending on how you want to manage attributes.
class Version(models.Model):
version = models.CharField(max_length=10)
class ProductAttributes(models.Model):
name = models.CharField(max_length=64)
description = models.CharField(max_length=255)
# other fields as necessary
class Product(models.Model):
name = models.CharField(max_length=64)
version = models.ForeignKey(Version)
attributes = models.ManyToManyField(ProductAttributes, related_name='products')
That should be your modelling sorted in a very basic way. Now, let's create some instances.
v1 = Version(version='1.0.0')
v1.save()
hosted = ProductAttributes(name='Hosted', description='We host the apps!')
hosted.save()
shiny = ProductAttributes(name='Shiny', description='I like shiny')
shiny.save()
p = Product(name='Web Based Email', version=v1)
p.save()
p.attributes.add(hosted)
p.attributes.add(shiny)
p.attributes.all()
# shows shiny and hosted!
You can tweak the ModelAdmin for Product such that you can add ProductAttributes inline when adding or editing a Product. You can also have a separate ModelAdmin for ProductAttributes so you can create a list of known Attributes that can be applied to products at a later date.
There are two basic approaches for this.
Use a document based db (ie, "NoSQL") like Couch or Mongo. These have flexible schemas, so allow for multiple variations on a product.
Use the Entity Attribute Value (wikipedia) schema pattern. django-eav is an app that provides this.
Decide to go with sub-classes with each Product as each has a limited set of specific attributes that won't change much or at all over time. Thanks for all the great feedback. Learned a lot :-)

How can I programmatically obtain the max_length of a Django model field?

Say I have a Django class something like this:
class Person(models.Model):
name = models.CharField(max_length=50)
# ...
How can I programatically obtain the max_length value for the name field?
Person._meta.get_field('name').max_length will give you this value. But having to use _meta suggests this is something you shouldn't do in normal usage.
Edit: as Carl pointed out, this naming is misleading and it does seem quite acceptable to use it: http://www.b-list.org/weblog/2007/nov/04/working-models/
Read more at Django Docs:
https://docs.djangoproject.com/en/dev/ref/models/meta/#django.db.models.options.Options.get_field
The question is regarding models, but for people trying to do the same for forms (that's how I ended up in this thread), I think this approach is quite simple and clear:
1. In a template:
{{form.name.field.max_length}}
2. In python code (e.g. in the view)
form.name.field.max_length

Categories

Resources