I have the following models structure:
class BaseMovie(models.Model):
movie = models.FileField('Movie')
width = models.IntegerField('Width')
height = models.IntegerField('Height')
duration = models.FloatField('Duration')
class SpecialMovie(models.model):
base_movie = models.ForeignKey(BaseMovie, 'Base movie')
# some other stuff
The idea behind is that I intend to use BaseMovie in several models.
My question is:
How can I set, in the SpecialMovie model, the location to which the special movies will be uploaded?
I think that storing only the metadata in the BaseMovie class and having the movie field with appropriate upload_to function in the SpecialMovie is not satisfying, because I would have to copy the code that fills the metadata in all the models with a foreign key to BaseMovie.
upload_to can be a callable; you could set it to a function that checks if the instance has a related SpecialMovie, and return the correct value accordingly.
Related
I'm am trying to create a view where the user will get the object with the largest value of a certain field in my Django model objects.
This is my model:
class LongTermCoinHistory(models.Model):
coin = models.ForeignKey(Coin,on_delete=models.CASCADE)
timestamp = models.BigIntegerField(default=0)
price = models.FloatField()
I want to get the object instance from my database that has the largest timestamp value.
How do I go about doing this?
LongTermCoinHistory.objects.latest("timestamp")
docs
I have the following model in django
class params(models.Model):
name = models.CharField(max_length=30, default = 'no_name')
cs_n = models.IntegerField(default=16)
alt_n = models.IntegerField(default=2)
opt_out = models.BooleanField(default=1)
at_n = models.IntegerField(default=4)
I want to create a new model with as many fields as at_n. For example, if the user enter "4" in at_n, I want this to create automatically:
class params(models.Model):
at_1 = models.IntegerField(default=2)
at_2 = models.IntegerField(default=2)
at_3 = models.IntegerField(default=2)
at_4 = models.IntegerField(default=2)
Thanks
This probably isn't a good data model to follow as Django models are intended to closely mirror database tables. For example, you wouldn't want to dynamically update the DDL of a table in a database because doing so places you at risk of messing up data that already exists in said table.
Instead, I think it would be a better approach for you to re-evaluate your data model.
For example, if there was a main object you were trying to tie these attributes to, then make a model for that main object and then make a separate model for main object attributes/values.
From there, you could use view logic to actually validate that the appropriate number of attributes assigned to a particular main object.
I'm thinking something kind of like this:
class MainModel(models.Model):
....
{Your main model attributes}
at_n = models.IntegerField(default=4)
....
class MainModelAttributes(model.Model):
main_model = models.ForeignKey(MainModel)
attr_value = models.IntegerField()
Then in your views.py file, you could use logic to make sure that the number of attributes on the MainModelAttributes model match the number stored in MainModel.at_n.
I have a model with a field that is a int type, that field have a default value
I'm trying to set a value in that field with post_generation but nothing is happening, the field stay with the default value, when I try to use .set I get the following error:
AttributeError: 'int' object has no attribute 'set'
this is the field that I'm trying to populate
#factory.post_generation
def priority(obj, create, extracted, **kwargs):
for series in range(obj.patrimony.count()): # this is a sequence of numbers
series += 1
obj.priority.set(series)
and this is the model, is just a simple model
class Series(models.Model):
priority = models.IntegerField(_("Priority"), default=0, null=True)
Can someone open my eyes please?
You are meeting two issues:
Setting the field value
Series.priority is always an int, and integers have no .set() method (they are immutable objects).
You should set it by using obj.priority = series
Setting the value at the right time
factory_boy creates objects in 3 steps:
1. Evaluate all pre-declarations (LazyAttribute, Sequence, etc.);
2. Create the object in the database (calling Series.objects.create(...))
3. Evaluate post-generation declarations
If obj.patrimony is known before creating the series, you could simply have:
class SeriesFactory(factory.django.DjangoModelFactory):
class Meta:
model = Series
priority = factory.LazyAttribute(lambda o: o.patrimony.count())
(I've also adjusted the declaration, since your for series in ... loop is strictly equivalent to obj.priority = obj.patrimony.count())
I am reading Excel using xlrd. One of the columns has the Bank name, which is linked to vehicle model via Foreign Key. When xlrd finishes reading a row, it should save that record to vehicle table. However getting the actual pk value and error that Vehicles.bank must a Banks instance.
After checking dozens of questions related to this issue, I found this one the most similar one, but still I am not getting the expected result.
The relevant Vehicle model section is as follows:
class Vehicles(models.Model):
stock = models.CharField(max_length=10, blank=False, db_index=True)
vin = models.CharField(max_length=17, blank=False, db_index=True)
sold = models.DateField(blank=True, null=True, db_index=True)
origin = models.CharField(max_length=10, blank=False, db_index=True)
bank = models.ForeignKey('banks.Banks', db_column='bank', null=True)
I am using python 2.7, django 1.5.4 and Postgresql 9.2.5. Dbshell utility does show that banks table has a Foreign contraint referring to vehicles table, via banks(id).
Since I am not using a form for this particular part, I think it does not matter whether I use a ModelForm or not.
Current scenario: Excel file has FBANK as the cell value. There is an existing record in banks table that contains FBANK in its name column, id=2. The python line is:
def bank(value):
return Banks.objects.get(name=value).id
With the above line, error is:
Cannot assign "2": "Vehicles.bank" must be a "Banks" instance.
If I remove the ".id" at the end, error is then:
Banks matching query does not exist.
Appreciate your help.
Ricardo
When saving Vehicle you need to pass Banks instance with corresponding bank name. See example, I suppose that you have all data in corresponding cells from 0 to 4, replace with your own cells numbers:
def get_bank_instance(bank_name):
try:
bank = Banks.objects.get(name=bank_name)
except Banks.DoesNotExist:
return None
return bank
# reading excel file here, we have list of cells in a row
for cell in cells:
bank = get_bank_instance(cell[4])
if bank:
# get other cells values to be saved in Vehicles
stock, vin, sold, origin = cell[0], cell[1], cell[2], cell[3]
Vehicles.create(bank=bank, stock=stock, vin=vin, sold=sold, origin=origin)
You also can create save instance of Vehicles passing bank id directly:
b_id = Banks.objects.get(name=bank_name).id
Vehicles.create(bank_id=b_id, stock=stock, vin=vin, sold=sold, origin=origin)
Update:
create() is a built-in model method to create and save into database model instance. If you are asking about "Add a classmethod on the model class" in Django docs, this is not the case, because you are just using built-in method for the model. For some cases you can use custom method for creating new models, but I would do so if I had to pass a lot of default attributes for the new instance.
Also, it's possible to create and save new model instance by using save():
bank_instance = Banks.objects.get(name=bank_name)
vehicle = Vehicles()
vehicle.bank = bank_instance
vehicle.stock = stock
vehicle.vin = vin
vehicle.sold = sold
vehicle.origin = origin
# without save() data will not be saved to db!
vehicle.save()
It's quite long and you always need to remember to call .save(), so it's a good idea to use .create()
You should be returning a Banks instance when you want to assign it to a Vehicle model instance; so you should not have the .id part at the end of the return value for your bank() method.
Secondly, if it says that it isn't finding the Banks instance, then you should check the value of your value parameter to see what it is and try to manually do a Banks.objects.get from your database. If it can't be found then there is probably another reason for this other than using the Django ORM incorrectly.
When you are assigning instances to other instances in Django, for example setting the Bank for a Vehicle it must be an instance of the model and not the id or pk value of model; this is stated in the other StackOverflow question that you reference in your question.
I've got a model that looks something like this
class SecretKey(Model):
user = ForeignKey('User', related_name='secret_keys')
created = DateTimeField(auto_now_add=True)
updated = DateTimeField(auto_now=True)
key = CharField(max_length=16, default=randstr(length=16))
purpose = PositiveIntegerField(choices=SecretKeyPurposes)
expiry_date = DateTimeField(default=datetime.datetime.now()+datetime.timedelta(days=7), null=True, blank=True)
You'll notice that the default value for key is a random 16-character string. Problem is, I think this value is getting cached and being used several times in a row. Is there any way I can get a different string every time? (I don't care about uniqueness/collisions)
Yes, the default will only be set when the Model metaclass is initialized, not when you create a new instance of SecretKey.
A solution is to make the default value a callable, in which case the function will be called each time a new instance is created.
def my_random_key():
return randstr(16)
class SecretKey(Model):
key = CharField(max_length=16, default=my_random_key)
You could, of course, also set the value in the model's __init__ function, but callables are cleaner and will still work with standard syntax like model = SecretKey(key='blah').