obj = Info(name= sub,question=response_dict["question"])
obj.save()
After saving the data how to update another field of the same table
obj.err_flag=1
obj.update()//Will this work
Just resave that instance:
obj.some_field = some_var
obj.save()
Django automatically knows when to UPDATE vs. INSERT your instance in the database.
This is explained in the
Django docs.
obj = Info(name=sub,question=response_dict["question"])
obj.save()
And then later you want to get it and update it (I'm assuming name is unique identifier):
obj = Info.objects.get(name=sub)
obj.err_flag=1
obj.save()
If in the question you mean to say same object or same row where you say same table, then if you do this
obj = Info(name= sub,question=response_dict["question"])
obj.save()
and then after a few lines you need to do this
obj = Info.objects.get(name=sub)
obj.err_flag=1
obj.save()
then obj = Info.objects.get(name=sub) is unnecessary.
You simply do
obj = Info(name= sub,question=response_dict["question"])
obj.save()
#
#do what you want to do, check what you want to check
#
obj.err_flag=1
obj.save()
Related
I want to update item quantity in a database or add to inventory if the UPC doesn't already exist. I am not sure how to write the logic. Here's what I have so far:
My view:
from django.contrib.auth.decorators import login_required
from .forms import AuditItemForm
from .models import AuditItem
import datetime
#login_required
def audit_inventory(request):
form = AuditItemForm(request.POST or None)
if form.is_valid():
form.save(commit=False)
form_upc = form.cleaned_data.get('upc')
qty = form.cleaned_data.get('qty')
for instance in AuditItem.objects.all():
if instance.upc == form_upc:
instance.qty += qty
instance.user = str(request.user)
instance.last_updated = datetime.datetime.now()
instance.save()
elif instance.upc != form_upc:
form.save(commit=True)
return redirect('/audit')
context = {
"form": form,
"title": "Audit Inventory",
}
return render(request, "audit.html", context)
What's wrong with my logic? It updates an item correctly but it doesn't allow me to add a new item that doesn't already exist.
Not sure if it is what you want but maybe try get_or_create() function it will return item and boolean value if it was created or pulled from database
form = AuditItemForm(request.POST or None)
if form.is_valid():
form.save(commit=False)
form_upc = form.cleaned_data.get('upc')
qty = form.cleaned_data.get('qty')
# get item or create new one if it doesn't exist
item, created = AuditItem.objects.get_or_create(upc=form_upc)
# if it already exist, update quantity
if not created:
item.qty += qty
item.user = str(request.user)
item.last_updated = datetime.datetime.now()
# whether item was created or updated save it to database
item.save()
What you need is update_or_create(defaults=None, ** kwargs)
Explanation:
A convenience method for updating an object with the given kwargs, creating a new one if necessary. The defaults is a dictionary of (field, value) pairs used to update the object. The values in defaults can be callables.
Returns a tuple of (object, created), where object is the created or updated object and created is a boolean specifying whether a new object was created.
The update_or_create method tries to fetch an object from database based on the given kwargs. If a match is found, it updates the fields passed in the defaults dictionary.
The example of this method is:
obj, created = Person.objects.update_or_create(
first_name='John', last_name='Lennon',
defaults={'first_name': 'Bob'},
)
For more information: https://docs.djangoproject.com/en/3.2/ref/models/querysets/#update-or-create
I want delete serializer's content to show.I am using Django Rest Framework.I am making a system return Json of serializers.Furthermore,I did not want to show user_id data. I wrote in views.py
class InfoViews(viewsets.ModelViewSet):
queryset = Info.objects.all()
serializer_class = InfoSerializer
lookup_field = 'id'
def update(self,request, *args, **kwargs):
obj = UserInfo.objects.get(pk=kwargs['id'])
data = request.data
info_serializers = InfoSerializer(obj, data = data)
if info_serializers.is_valid(raise_exception=True):
info_serializers.save()
del info_serializers.data['user_id']
return JsonResponse(info_serializers.data)
Now all son data is shown.What is wrong in my code?How should I fix this?
You can specify in the serializers which fields you want to include or exclude in the response:
http://www.django-rest-framework.org/api-guide/serializers/#specifying-which-fields-to-include
look for : Specifying which fields to include
hope this helpes
First Clone the object into a new variable and then pop the key.
if info_serializers.is_valid(raise_exception=True):
info_serializers.save()
import copy
new = copy.deepcopy(info_serializers.data)
new.pop('user_id', None)
return JsonResponse(new)
I have a very big model, with steps form. So I decided on each page get previous object and update his attributes in form. In first form I do:
def save(self, commit=False):
obj = super(FirstForm, self).save(commit=False)
obj.id = 999999999
self.request.session['obj'] = pickle.dumps(obj)
self.request.session.save()
return obj
Id is required by mtm. So I set default one.
Then on last step in view I do:
obj = self.request.session.get('obj')
obj = pickle.loads(obj)
obj.id = None # remove temporary id
obj.save()
But Django save two objects. One normal object and one empty with id 999999999 . Why ?
I tried do:
obj = super(FirstForm, self).save(commit=False)
obj.id = 999999999
self.request.session['obj'] = pickle.dumps(obj)
self.request.session.save()
obj.delete()
But it didn't help.
This likely happens because the id field is used as a primary key for your model. When you set id to None, and then save the object, it'll actually create a new object with an id that's iterated sequentially from the previous last object.
I want to create an object only if there's no other object with the same ID already in the database. The code below would create the same item if one the parameters below like the State was modified.
returns = Return.objects.all()
for ret in returns:
obj, created = Return.objects.get_or_create(ItemID="UUID",
ItemName="Hodaddy", State="Started")
obj.save()
get_or_create works off all the arguments provided to find the object.
What you need to do instead is use the special defaults argument to provide the new value for a field that you don't want to filter on.
In your case, you only want the UUID field to be unique, and so you provide the other two members as defaults.
obj, created = Return.objects.get_or_create(ItemID="UUID",
defaults={ItemName:"Hodaddy", State:"Started"})
Then you can make further decisions based on the value of created. I am not sure why you're iterating over all the Returns in the original question?
If you know the id, you can query for it:
In your question, you have:
returns = Return.objects.all()
for ret in returns:
return_in_database = Return.objects.filter(ItemId="UUID").exists()
if not return_in_database:
obj, created = Return.objects.get_or_create(ItemID="UUID",
ItemName="Hodaddy", State="Started")
obj.save()
This can be done as:
if not Return.objects.filter(ItemId="UUID").exists():
obj, created = Return.objects.get_or_create(ItemID="UUID",
ItemName="Hodaddy", State="Started")
obj.save()
As you can see, I've removed the for loop, as you were not using the variable ret anywhere, so no need to iterate over all Return objects. The above is functionally equivalent to what you had. :)
OR:
You can write your own manager with a create_or_update method inside your models.py
class ReturnManager(models.Manager):
def create_or_update(self, **kwargs):
new_return = Return(**kwargs)
existing = Return.objects.filter(ItemId=new_returns.ItemID).first()
if existing:
new_return.pk = existing.pk
new_return.id = existing.id
new_return.save()
return new_return
You would then assign this to your Return model
class Return(model.Models):
# your object fields here
objects = ReturnManager()
You need to change the param in the query, to just constraint the object lookup on ItemID. Once, a new object is returned you can update the ItemName and State
obj, created = Return.objects.get_or_create(ItemID="UUID")
if created:
obj.ItemName="<item-name>"
obj.State="<Started>"
obj.save()
I've been working with Scrapy but run into a bit of a problem.
DjangoItem has a save method to persist items using the Django ORM. This is great, except that if I run a scraper multiple times, new items will be created in the database even though I may just want to update a previous value.
After looking at the documentation and source code, I don't see any means to update existing items.
I know that I could call out to the ORM to see if an item exists and update it, but it would mean calling out to the database for every single object and then again to save the item.
How can I update items if they already exist?
Unfortunately, the best way that I found to accomplish this is to do exactly what was stated: Check if the item exists in the database using django_model.objects.get, then update it if it does.
In my settings file, I added the new pipeline:
ITEM_PIPELINES = {
# ...
# Last pipeline, because further changes won't be saved.
'apps.scrapy.pipelines.ItemPersistencePipeline': 999
}
I created some helper methods to handle the work of creating the item model, and creating a new one if necessary:
def item_to_model(item):
model_class = getattr(item, 'django_model')
if not model_class:
raise TypeError("Item is not a `DjangoItem` or is misconfigured")
return item.instance
def get_or_create(model):
model_class = type(model)
created = False
# Normally, we would use `get_or_create`. However, `get_or_create` would
# match all properties of an object (i.e. create a new object
# anytime it changed) rather than update an existing object.
#
# Instead, we do the two steps separately
try:
# We have no unique identifier at the moment; use the name for now.
obj = model_class.objects.get(name=model.name)
except model_class.DoesNotExist:
created = True
obj = model # DjangoItem created a model for us.
return (obj, created)
def update_model(destination, source, commit=True):
pk = destination.pk
source_dict = model_to_dict(source)
for (key, value) in source_dict.items():
setattr(destination, key, value)
setattr(destination, 'pk', pk)
if commit:
destination.save()
return destination
Then, the final pipeline is fairly straightforward:
class ItemPersistencePipeline(object):
def process_item(self, item, spider):
try:
item_model = item_to_model(item)
except TypeError:
return item
model, created = get_or_create(item_model)
update_model(model, item_model)
return item
I think it could be done more simply with
class DjangoSavePipeline(object):
def process_item(self, item, spider):
try:
product = Product.objects.get(myunique_id=item['myunique_id'])
# Already exists, just update it
instance = item.save(commit=False)
instance.pk = product.pk
except Product.DoesNotExist:
pass
item.save()
return item
Assuming your django model has some unique id from the scraped data, such as a product id, and here assuming your Django model is called Product.
for related models with foreignkeys
def update_model(destination, source, commit=True):
pk = destination.pk
source_fields = fields_for_model(source)
for key in source_fields.keys():
setattr(destination, key, getattr(source, key))
setattr(destination, 'pk', pk)
if commit:
destination.save()
return destination