i want to generate an unique id code in my model
for example -
id want to generate
Can anyone Kindly help me in the same?
i Want id in the table as shown below-
class parameter(models.Model)
name=models.models.CharField(max_length=50)
type=model.#should come from another table
subtype=model.#should come from another table
id= # should compile all the above as in picture
thanks
I think you should not store the unique id in DB, because you can easily generate it by a property method:
class Parameter(models.Model)
name=models.models.CharField(max_length=50)
type=model.ForeignKey(Type)
subtype=model.ForeignKey(SubType)
product_type=model.ForeignKey(ProductType)
serial_no = models.CharField()
#property
def generated_id(self):
return '{}/{}/{}/{}'.format(self.type_id, self.subtype_id, self.product_type_id, self.serial_no.zfill(2))
If you intend to display it in admin site, then simply try like this:
#admin.register(Parameter)
class ParameterAdmin(admin.ModelAdmin):
model = Parameter
fields = ['type', 'sub_type', 'product_type', 'serial_no', 'generated_id']
readonly_fields = ('generated_id',)
Update
If you want to store in in DB, then you need to override the save method of the models. Like this:
class Parameter(models.Model)
name=models.models.CharField(max_length=50)
type=model.ForeignKey(Type)
subtype=model.ForeignKey(SubType)
product_type=model.ForeignKey(ProductType)
serial_no = models.CharField()
generated_id = models.CharField()
def generate_id(self):
return '{}/{}/{}/{}'.format(self.type_id, self.subtype_id, self.product_type_id, self.serial_no.zfill(2))
def save(self, *args, **kwargs):
self.generated_id = self.generate_id()
super().save(*args, **kwargs)
Related
I have a model which store an API response. I want to pass a dict which contain response to update a model.
class Currency_Trending_Info(models.Model):
"""Stores a market's last price as well as other stats based on a 24-hour sliding window."""
crypto_currency = models.ForeignKey(Crypto_Currency, on_delete=models.CASCADE)
market = models.CharField(max_length=30, blank=True, null=False)
last_volume = models.DecimalField(max_digits=18, decimal_places=9)
last_volume_to = models.DecimalField(max_digits=18, decimal_places=9)
last_trade_id = models.BigIntegerField()
...
...
but API response format looks like:
{
...
'TYPE':'5',
'MARKET':'CCCAGG',
'FROMSYMBOL':'BTC',
'TOSYMBOL':'USD',
'FLAGS':'4',
'PRICE':6276.14,
'LASTUPDATE':1539279469,
'LASTVOLUME':0.03845327,
'LASTVOLUMETO':239.21394734299997,
'LASTTRADEID':'52275450'
...
}
so my question is is a there way to define alternative name to a field or should I just change model fields to correspond API response e.g. lastvolume = models.DecimalField(max_digits=18, decimal_places=9) (and of course use the key.lower() to turn a key into a lower case string.)
any suggestions are welcome
edit:
saving to the db
entry=Crypto_Currency(crypto_currency="BTC", price=6276, unix_timestamp=1539279469)
entry.save()
# Dictionary with the trending data
currency_info = Currency_Trending_Info(crypto_currency=entry,**dic)
One approach is override model.save method to do custom task while saving object. From there you can manually assign value to each field and save it. Refer http://books.agiliq.com/projects/django-admin-cookbook/en/latest/override_save.html or official doc .
It will look something like this:
class Crypto(models.Model):
...
def save(self, *args, **kwargs):
self.attribte_name = kwargs['value']
super(Model, self).save(*args, **kwargs)
Don't forget to call super. Because db not gonna change if you miss that.
I am writing a custom widget for multiple image uploads. My models are:
models.py
class Room(models.Model):
....
....
class Picture (models.Model):
room = models.ForeignKey(Room)
url=models.ImageField(upload_to='slider', height_field=None, width_field=None, max_length=100)
def __unicode__(self):
return str(self.url)
I want to create custom widget which allow multiple image upload to be shown on rooms form
This is what I tried so far:
forms.py
class MultyImageWidget(forms.Widget):
....
def render(self, name, value, attrs=None):
context = {
'images': Picture.objects.filter(room = *room_id_of_currently_edited_room*)
# OR
# Any another way to get set of images from pictures table
}
return mark_safe(render_to_string(self.template_name, context))
class RoomsForm(forms.ModelForm):
gallery = forms.ImageField(widget=MultyImageWidget, required=False)
class Meta:
model = Room
fields = '__all__'
So problem is, I don't have gallery field in room model but I want to use widget to manage pictures which is stored in picture table similar to how one can manage data through inlines.
How to get id of room which is currently edited from my widget?
Or is there any other way to get related pictures?
Thanks
I believe you are using a wrong approach to your problem. Widget should only be responsible of displaying data and should not care about where that data come from. your render method accepts a value parameter, which is used to pass data to widget, so your render should look similar to this:
class MultyImageWidget(forms.Widget):
....
def render(self, name, value, attrs=None):
context = {
'images': value
}
return mark_safe(render_to_string(self.template_name, context))
Now we need to pass the needed Picture queryset. We can do this via form - and that what forms are for. You provided no context and I cannot comment yet to ask for details, but I suppose you are using a view to construct this form. If it is true, let's say we have some view, then we can do it this way:
def gallery_view(request, *args, **kwargs):
....
room = # get your room (maybe you pass ID via request or via arg or kwarg)
pictures = Picture.objects.filter(room=room) # or you can do room.picture_set.all()
form = RoomsForm(initial={'gallery': pictures})
....
If you are using this form with Django admin, a form has instance attribute and you can code like this:
class RoomsForm(forms.ModelForm):
gallery = forms.ImageField(widget=MultyImageWidget, required=False)
class Meta:
model = Room
fields = '__all__'
def __init__(self, *args, **kwargs):
super(RoomsForm, self).__init__(*args, **kwargs) # you may omit parameters to super in python 3
if self.instance:
self.fields['gallery'].initial = Picture.objects.filter(room=self.instance)
I hope this solves your problem
I have for example something like this:
class Order(models.Model):
user= models.ForeignKey(User)
class OrderLines(models.Model):
product = models.ForeignKey(Product)
quanity = models.PositiveSmallIntegerField()
order = models.ForeignKey(Order)
Now on my page want to do something like that (maybe my approach in design is wrong):
I receive POST data with product_id and quanity and store it as simple dictionary in session as 'ORDER_LINES' variable
When user clicks "Make order" I want to create Order object simply:
(I'm using generic views)
class ShowOrderPreview(TemplateView):
template_name = "shop/order_preview.html"
http_method_names = ['get']
def get_context_data(self, **kwargs):
context = super(ShowOrderPreview, self).get_context_data(**kwargs)
order = Order(user = self.request.user)
for product, quanity in self.request.session.get('ORDER_LINES', {}):
order.orderlines_set.add( product=get_object_or_404(Product, pk=product_id), quanity=quanity)
context['tmp_order'] = order
return context
I dont want to that order be stored in database and only after user confirmation create it again and save.
I'm receiving: "Column 'order_id' cannot be null" on line order.orderlines_set.add(...
I know that the fastest solution will be create something like DummyOrder and DummyOrderLines with structure like the sam like my main Order and OrderLines object
I'm using Django 1.4.1.
I have a CarType that has a ForeignKey BodyMaterial in my models.py:
class BodyMaterial(models.Model):
location = models.ForeignKey('CarType')
name = models.CharField(max_length=255)
class CarType(models.Model):
name = models.CharField(max_length=255)
default_body_material = models.ForeignKey(BodyMaterial, null = True, blank = True, default = "", limit_choices_to={'location__exact': 1})
BodyMaterial is an Inline in CarType in my admin.py:
class BodyMaterial_Inline(admin.StackedInline):
model = BodyMaterial
extra = 1
class CarType_Admin(admin.ModelAdmin):
inlines = [BodyMaterial_Inline]
admin.site.register(CarType, CarType_Admin)
I would like to filter the ForeignKey for default_body_material to show only the relevant BodyMaterials (the ones that appear/added on the same admin page). For example, I created a 2 seat CarType and in the same page added some BodyMaterials. Then I create an SVU CarType and some other BodyMaterials. When I go back to the 2 seat CarType, I would like to see only the relevant BodyMaterials in the drop-down for default_body_material.
I try to filter using limit_choices_to on the id. So I'm doing this using post_init because the id for the object in determined in runtime:
def setID(**kwargs):
instance = kwargs.get('instance')
default_body_material = instance._meta.get_field_by_name('default_body_material')[0]
default_body_material.limit_choices_to = {'location__exact': instance.id}
post_init.connect(setID, CarType)
Unfortunately, that does nothing. What am I missing? Is there a beter why of filtering ForeignKey for my purposes (this is probably very basic)?
Note that this question is only for the admin interface.
Just use a custom ModelForm:
class CarTypeAdminForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(CarTypeAdminForm, self).__init__(*args, **kwargs)
# Can't limit it until instance has been saved at least once
if self.instance.pk:
self.fields['default_body_material'].queryset = \
self.fields['default_body_material'].queryset \
.filter(location=self.instance)
class CarTypeAdmin(admin.ModelAdmin):
form = CarTypeAdminForm
...
You want to look at overriding the queryset function for your inline.
I have a Django Model that looks like this:
class MyModel(models.Model):
field1 = models.IntegerField()
field2 = models.IntegerField()
nonDbField = SomeObject()
objects = MyCustomManager()
field1 is actually a PK to an abstract class of SomeObject.
I want a custom manager that for every value returned by any of the functions (all, filter, get, etc) does the following:
value.nonDbField = SomeObject.objects.get(pk=value.field1)
I've tested that I can manually override get like so:
class MyCustomManager(models.Manager):
def get(self, *args, **kwargs):
value = super(MyCustomManager, self).get(*args, **kwargs)
value.nonDbField = SomeObject.objects.get(listid=value.itemListID)
return value
but wondered if there was an easier way to do it across all functions.
There's going to be plenty of you that will say, "Why are you doing this?". It has to do with a model inheritance of a legacy, but still active database.
If you need nonDbField's value to be related to the field1 (or any other field in the model) you can try something like this:
Class MyModel(models.Model):
# your fields here...
def _nonDbField(self):
return SomeObject.objects.get(pk=self.field1)
nonDbField = property(_nonDbField)
This allows you to do something like this:
MyModel.objects.get(pk=1).nonDbField
Keep in mind that you are making a database query each time you access nonDbField (which may or may not be detrimental to your DB performance).
you can use property for your calculated fields
Class MyModel(models.Model):
# your fields here...
first_name = models.CharField()
last_name = models.CharField()
#property
def fullname(self):
return f"{self.first_name} {self.last_name}"
This allows you to do something like this:
obj = MyModel.objects.get(pk=1)
print(obj.fullname)