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.
Related
I have a task to create a simple post API to send a visitor messages through a contact form that contain fields like full_name,address,phone etc. But instead of creating a model, I have to use an already existing model which has a Jsonfield. Now what I need to do is to use that jsonfield which will have all the fields like name, address etc.
class Core(models.Model):
"""
Model that saves the corresponding credentials for the slug.
"""
slug = models.CharField(max_length=255, null=False)
example = models.JSONField(null=False, default=dict)
def __str__(self) -> str:
return self.slug
If it was done in a regular way by creating a model, it would have been like this.
class Contacts(models.Model):
full_name = models.CharField(max_length=100,blank=True,default="")
email = models.EmailField()
phone = models.CharField(max_length= 16)
address = models.CharField(max_length=255,blank=True,default="")
message = RichTextField()
def __str__(self):
return self.email
Now, how should I send these fields data in a dictionary without in that JsonField without creating a Contacts model?
First of all, this question is not clear. Please ask your question in a clearer way. I hope the way below helps you.
This field keeps data like;
{"full_name":"John Doe", "email": "johndoe#doe.com", "phone":"XXXXXXXXXXX"}
You may create dictionary and assign to field. Also you may create json data like this;
json_example = json.dumps(full_name="John Doe, email="johndoe#doe.com, phone="XXXXXXXXXXX")
and then create a Core object ;
core = Core(example = json_example)
core.save()
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)
I am using soft deletes on one of my models in Django, and I am overwriting the default manager to always return active records only, using something like:
class ActiveRecordManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(is_deleted=False)
class Tag(models.Model):
is_deleted = models.BooleanField(default=False, db_index=True)
objects = ActiveRecordManager()
class Photo(models.Model):
tag = models.ForeignKey(Tag, on_delete=models.CASCADE, related_name="photos")
objects = ActiveRecordManager()
All works well. However, when I do:
tag = Tag.objects.get(pk=100)
And then I try to get the associated photos:
photos = tag.photos.all()
Then I get photos that are deleted. I only want to return objects that are not deleted (so my regular objects list. I was reading about _base_mangers in Django, which seems to control this, but the documentation recommends against filtering objects out:
If you override the get_queryset() method and filter out any rows,
Django will return incorrect results. Don’t do that. A manager that
filters results in get_queryset() is not appropriate for use as a base
manager.
But what I am not clear about is how I am supposed to filter these results. Any thoughts?
UPDATE:
I was asked to explain how this question is different from this one:
How to use custom manager with related objects?
In this 8 year old question they mention a deprecated method. That deprecated method is superseded by the method I outline below (base_managers) which according to the documentation I should not use. If people think I should use it, can you please elaborate?
why not use custom query methods instead of overriding manager as it may produce problems for example in admin pages?
class ActiveModelQuerySet(models.QuerySet):
def not_active(self, *args, **kwargs):
return self.filter(is_deleted=True, *args, **kwargs)
def active(self, *args, **kwargs):
return self.filter(is_deleted=False, *args, **kwargs)
class Tag(models.Model):
is_deleted = models.BooleanField(default=False, db_index=True)
objects = ActiveModelQuerySet().as_manager()
class Photo(models.Model):
tag = models.ForeignKey(Tag, on_delete=models.CASCADE, related_name="photos")
is_deleted = models.BooleanField(default=False, db_index=True)
objects = ActiveModelQuerySet().as_manager()
you can then filter your models however you want
tag = Tag.objects.active(pk=100)
deleted_tags = Tag.objects.not_active()
photos = tag.photos.active()
also note that you need is_deleted attribute in all your models that have the soft delete functionality like Photo in your case
What I'm trying to do is a 2 tier search with drop down menus using Select widget, the results will be a listing of the fields from my Meta.model. the first Tier is a a State listing from State.model. Upon a select it is supposed to list out all of the cities with in the selected state, the problem I'm having (and I think its due to my lack of knowledge) is that the city listing is not filtered but a listing of all cities in my database regardless of state. I'm not sure where or how to pass my variable to be able invoke my .filter() statement.
models.py
class Meta(models.Model):
rcabbr = models.CharField(max_length = 15)
slug = models.SlugField(unique=False)
state = models.ForeignKey('State')
rc_state = models.CharField(max_length = 3)
oerp = models.CharField(max_length=18)
subgrp = models.SlugField()
sonus_pic = models.CharField(max_length=8)
ems = models.CharField(max_length=14)
agc = models.CharField(max_length=14)
def __unicode__(self):
return self.rcabbr
class State(models.Model):
name = models.CharField(max_length=2)
slug = models.SlugField(unique=True)
state_long = models.CharField(max_length=15)
owning_site = models.CharField(max_length=12)
def __unicode__(self):
return self.name
return self.state_long
forms.py
class states(forms.Form):
invent = [(k.name,k.state_long) for k in State.objects.all()]
rclist = forms.ChoiceField(widget=forms.Select, choices=invent)
class rateCenter(forms.Form):
invention = [(k.id,k.rcabbr,k.rc_state) for k in Meta.objects.all()]
rcviews = forms.ChoiceField(widget=forms.Select, choices=invention)
views.py
def StateAll(request):
""" This lists out all of the states within the database that
are served"""
rclist = states()
return render(request, 'statelist.html',{'rclist': rclist})
def RcView(request):
""" this should list all the rateCenters within
the state that was selected in StateAll() """
rclist = request.GET['rclist']
forms = rateCenter()
return render(request, 'rclist.html',{'forms': forms})
Logic tells me I should to do my .filter() statement in the forms.py but unsure how to pass the result from the request.GET in StateAll() view. I do have the debug_toolbar installed so I can see the variable u'rclist' and the value u'LA' (my test state). I had this working 100% using hyperlinks however the size of my test database is miniscule in comparison to what is going to be in the production version and HREF's are just not possible.
my understanding is:
ChainedForeignKey(LinkedModel, LinkedModel.field = "field in first Tier", chained_model_field = "current model_field")
so simple model should I think be something like this?
def State(model.models):
name = models.CharField(max_length=20) #this is the state abbreviation
state_long = models.CharFeild(max_length=20)#this is state long form
def Meta(model.models):
state = models.CharField(max_length=20)
slug = models.SlugField(unique = False) #same values as rcabbr
rcabbr = ChainedForeignKey(State, chained_field = "state_long",
chained_model_field = "slug")
.....
Does that look about right........so the First Field in the drop down should be the State_long, once selected the next should be the slug?. at which time the slug should be passed to my urls and the views for the that final page.
I am going to try this however I'm not 100% sure how to do my views and if I need to do something with forms page or does this cover it? The documentation is not user friendly for someone new to this so any input would be most appreciated!
There are many third party libraries django-smart-selects and dajax come to mind - that will automate this for you along with provide you the necessary javascript to filter the form fields on the fly.
If you are investigating those, here is how you would do it with just the django forms:
class RateCenterForm(forms.Form):
rate_center = forms.ModelChoiceField(queryset=Meta.objects.all())
def __init__(self, *args, **kwargs):
state = kwargs.pop('state')
super(RaterCenterForm, self).__init__(*args, **kwargs)
self.fields['rate_center'].queryset = Meta.objects.filter(state=state)
A ModelChoiceField is a select drop down that takes its values from a model.
Now in your view, you would call it like this:
def show_rate_centers(request):
form = RateCenterForm(state='SomeState')
# .. your normal logic here
This may be a design question.
Question is "What is the best way to find offers that needs to have feedback sent by logged in user". In Feedbacks site there are 3 tabs: "Sent", "Received", "Send feedback".
"Send feedback" tab there's a table with "Offer id","username(buyer/sender" and "Send feedback" link pointing to feedback form.
Here's the code which should help understand what I mean.
Offers are displayed until some user buys it.
Offer is being closed, and new Order (storing order details) instance is created for this offer.
I'm trying to implement a Feedback app, where both sides of offer transaction can
send feedback about transaction.
Let's skip the "ended" or "running" offer problem.
class Offer(models.Model):
"""Offer is displayed for 5 days, then it's being ended by run everyday cron script.
If someone buys the offer end_time is being set, and offer is treated as ended.
Both sides of transaction may send feedback.
"""
whose = models.ForeignKey(User, verbose_name="User who has created the offer")
end_time = models.DateTimeField(blank=True, null=True, help_text="")
field = ()
fields2 = ()
order = models.ForeignKey(Order, balnk=True, null=True, help_text="Order details")
class Order(models.Model):
"""stores order details like user, date, ip etc."""
order_1_field_details = ()
who = models.ForeignKey(User, verbose_name="User who bought the offer")
offer_id = models.PositiveIntegerField("know it's unnecessary")
offer_data = models.TextField('offer data dict here')
class Feedback(models.Model):
offer_id = models.PositiveIntegerField()
sent_by = models.ForeignKey(User, verbose_name="Offer sender")
received_by = models.ForeignKey(User, verbose_name="Offer receiver")
def get_offer(self):
try:
Offer.objects.get(id=self.offer_id)
except Offer.DoesNotExist:
return None # offer moved to archive
In first draft there was a offer = models.ForeignKey(Offer) instead of offer_id field,
but I am going to move some old offers from Offer table to another one for archiving.
I would like the feedback stay even if I 'archive' the offer. In feedback list there will be an 'Offer id" link and for offers older than 60 days user will see "moved to archive" when clicking "details".
All I can think of at the moment is getting offers which hasn't expired, but there was a buyer.
ended() is a manager returning self.filter(end_date__isnull=False)
offers_with_buyer = models.Q(Offer.objects.ended().filter(whose__exact=request.user, order__isnull=False) | models.Q(Offer.objects.ended().filter(order__who__exact=request.user)
How do I check if there's a feedback for these offers ?
I know I should return user and offer id from queryset above and check if they exist in Feedback.offer_id and Feedback.sent_by.. or maybe I should change model design completely ...
First, how you're handling the end date is very contrived. If the offer ends 5 days after it's created, then just set that automatically:
from datetime import datetime, timedelta
class Offer(models.Model):
...
def save(self, *args, **kwargs):
self.end_date = datetime.now() + timedelta(days=5)
super(Offer, self).save(*args, **kwargs)
Then, just modify your ended manager to return instead: self.filter(end_date__lte=datetime.now())
However, I generally prefer to add additional methods to my default manager to deal with the data in various ways:
class OfferQuerySet(models.query.QuerySet):
def live(self):
return self.filter(end_date__gt=datetime.now())
def ended(self):
return self.filter(end_date__lte=datetime.now())
class OfferManager(models.Manager):
use_for_related_fields = True
def get_query_set(self):
return OffersQuerySet(self.model)
def live(self, *args, **kwargs):
return self.get_query_set().live(*args, **kwargs)
def ended(self, *args, **kwargs):
return self.get_query_set().ended(*args, **kwargs)
(Defining a custom QuerySet and then using methods on the Manager that just proxy to the QuerySet is the way the Django core team does it, and allows you to use the methods anywhere in the chain, instead of just the front.)
As far as "archiving" your Offers go, it's extremely bad practice to divvy out similar data into two different models/tables. It's exponentially increases the order of complexity in your app. If you want to "archive" an offer. Add a field such as:
is_archived = models.BooleanField(default=False)
You can then create another method in your Manager and QuerySet subclasses to filter out just archived or live offers:
def live(self):
return self.filter(is_archived=False, end_date__gt=datetime.now())
def archived(self):
return self.filter(is_archived=True)
If you really need another model (such as for a separate view in the admin for just archived offers) you can create a proxy model:
class ArchivedOfferManager(models.Manager):
def get_query_set(self):
return super(ArchivedOfferManager, self).get_query_set().filter(is_archived=True)
def create(self, **kwargs):
kwargs['is_archived'] = True
return super(ArchivedOfferManager, self).create(**kwargs)
class ArchivedOffer(models.Model)
class Meta:
proxy = True
objects = ArchivedOfferManager()
def save(self, *args, **kwargs):
self.is_archived = True
super(ArchivedOffer, self).save(*args, **kwargs)