Django - Saving data without using input fields/forms - django

I am a novice, apologies if this question seems silly. I need to save some data into MySQL database. There are no input fields. The user should click a button, and a table is updated. The data to be saved is two foreign keys and a PK.
Here is my model
class Bids(models.Model):
id=models.AutoField(primary_key=True)
userid = models.ForeignKey(Writer, on_delete=models.DO_NOTHING, related_name='userid ')
orderid = models.ForeignKey(Orders, on_delete=models.DO_NOTHING, related_name='orderids')
biddatetime=models.DateTimeField(auto_now_add=True)
I have tried writing several functions to save these fields into table bids but no joy so far. Hers's a sample.
def saveBid(request):
if request.method!= "POST":
return HttpResponse("Action Not Allowed")
else:
biddatetime=request.POST.get('biddatetime')
bids= Bids(biddatetime=biddatetime)
order=Orders(id=id)
user= CustomUser()
user.save()
bids.save()
Pls assist

I would try sending a POST request to saveBid using Postman and what error you're getting. Post the response from postman here for more help.
It could be that
biddatetime is a string and not a datetime.
On row order=Orders(id=id) you have no variable named id in your code, this will raise error.
In your model Bids the fields userid and orderid do not allow null and blank.

You can use strptime() to convert biddatetime to datetime object.
Try something like that:
from datetime import datetime
def saveBid(request):
if request.method != "POST":
return HttpResponse("Action Not Allowed")
else:
query = request.POST
# See Format Codes - link below
biddatetime = datetime.strptime(query.get('biddatetime'), "%Y-%m-%d")
# get Order
order = Orders.objects.get(id=query.get("order_id")
# create CustomUser
user = CustomUser.objects.create(username="username")
# create Bids
bids = Bids.objects.create(biddatetime=biddatetime, userid=user, orderid=order)
create() method:
create(**kwargs)
A convenience method for creating an object and saving it all in one
step. Thus:
p = Person.objects.create(first_name="Bruce", last_name="Springsteen")
Linkt to Format Codes.
See also Creating objects.

Any reason why you are not using django Form or ModelForm?
class BidForm(forms.Form):
biddatetime = forms.DateTimeField()
.... // other fields
#require_POST
def saveBid(request):
form = BidForm(request.POST)
if form.is_valid():
biddatetime = form.cleaned_data.get('biddatetime')
... // do same for similar fields.
...// after user save
user.refresh_from_db() // post insert you will get the id value for the row
bids = Bids(
biddatetime=biddatetime,
userid=user.userid,
orderid=order.orderids)
bids.save()
I am assuming you are using the id value for user after save if thats not the case you can ignore it.

Related

Django DRF - update profile using serializer + json

I've been bashing my head against the wall on this for about 3 full days now and probably read every thread on SO. Warning = I am not very good with Django REST or indeed Python.
To summarise, each user profile has 11 football players they have initially selected. I now want to update/change these players by POSTing json info.
views.py
elif request.method == 'POST':
jsondata = dict(request.data)
profile = Profile.objects.get(user=request.user)
serializer = ProfileSerializer(profile, data=jsondata, partial=True)
if serializer.is_valid():
serializer.save()
return JsonResponse(serializer.data, status=201)
Serializers.py
class ProfileSerializer(serializers.ModelSerializer):
"""
Serializing all the Players
"""
#user = serializers.StringRelatedField()
GK1 = PlayerSerializer()
DF1 = PlayerSerializer()
DF2 = PlayerSerializer()
DF3 = PlayerSerializer()
DF4 = PlayerSerializer()
MF1 = PlayerSerializer()
MF2 = PlayerSerializer()
MF3 = PlayerSerializer()
MF4 = PlayerSerializer()
FW1 = PlayerSerializer()
FW2 = PlayerSerializer()
def create(self, validated_data):
return Profile.objects.create(**validated_data)
class Meta:
model = Profile
fields = ( "GK1", "DF1", "DF2", "DF3", "DF4", "MF1", "MF2", "MF3", "MF4", "MF5", "FW1", "FW2",)
Right now as a test I am trying to update simply GK1. I know that I am getting correct json data via POST. I also know the instance data is the original data. However it just will not save/update!!! I have overridden the update method as a test:
def update(self, instance, validated_data):
setattr(instance, "GK1.id", validated_data['GK1']['id'])
instance.save()
return instance
### set the id of GK1 to the id that arrives via POST
### GK1.id gives me '1008' - a Player object
### validated_data['GK1']['id'] gives me '1025' - id of another player
Nothing happens - the id does not change in the DB :(
Here's my main question -
validated_data is an OrderedDict (fine)
instance is a User Profile object.
How do I squeeze the OrderedDict data into the Profile object? Can I do this simply by referencing the Primary Foreign Key? I.e. id?
I've very sorry about how vague this is and perhaps the lack of code. But the DRF tutorial is not clear imho. Any help much appreciated.
EDIT - json data / validated_data added to comments
EDIT2 - I have a working solution
I've changed the update method to do the following for each player:
instance.GK1 = PlayerID.objects.get(id=validated_data['GK1'].pop('id'))
Or in other words, the instance was looking for Player OBJECTS (and not a string representation of the id). Therefore I popped out the id and filtered (or .get) by the id of the object.
Thanks for reading, I have a massive weight off my shoulders...
I've changed the update method to do the following for each player:
instance.GK1 = PlayerID.objects.get(id=validated_data['GK1'].pop('id'))
Or in other words, the instance was looking for Player OBJECTS (and not a string representation of the id). Therefore I popped out the id and filtered (or .get) by the id of the object.
Thanks for reading, I have a massive weight off my shoulders...

overriding django formset initial data dynamically

Ok im new to django
So ive got a situation where i want a formset to have dynamic initial data
So basically here is what im looking for.
each form in the formset to have a different UserID
and a set of groups permission which they can choose from based from the initial data
here is my form
class assignGroupPermissionToUser(forms.ModelForm):
UserID = forms.ModelChoiceField(queryset=None)
Groups = forms.ModelMultipleCHoiceField(queryset=None, widget=FilteredSelectMultiple("Groups")
class Meta:
model=User
def __init__(self,*args,**kwargs):
super().__init__(*args,**kwargs)
Userid = kwargs.pop("UserID")
self.fields['UserID'].queryset =User.objects.get(UserID=Userid)
Permissions = kwargs.pop("Groups")
listofPermission = None
for each perm in permission:
listofPermission |= Permissions.objects.filter(GroupID=perm)
self.fields['Groups'].queryset = listofPermission
the data i wanna pass is built into a list like so
it is called
completeList
> completeList =[['13452',{'group1':'Admin','group2':'FrontDesk'}],['3532','group1':'Supervisors','group2':'ReadOnly;}]]
where the first value in each nested loop is the UserID, and the dictionary is the groups they can choose from.
override method in View.py
....
form = assignGroupPermissionToUser()
assignment = formset_factory(form,extra=0)
formset = [ assignment.__init__(completeList[x][0],completeList[x][1]) for x in range(len(completeList))]
then i get an error that str object has no 'is_bound' field line 58 of formset.py
im trytin to get this data to show up on each form and based on the user
it will be all different but everything i try to override it fails for initial form so here i am stuck
note that the Group attribute in the modelform has a widget which is used in the admin section to filter from multiple choices.
settings
Django= 1.8
python 3.5
i erased all this code and just did two loops like so
formset = assignments(initial=[{'UserID': listofUserID[x] } for x in range(len(completeList))])
#then
for form in formset:
form.fields['permissions'].queryset = querysetiwant

Django validate data when updating model with primary key

I am having trouble with updating fields of a model instance. The model is as follows:
class commonInfo(models.Model):
mothers_id = models.IntegerField(primary_key=True)
date = models.DateField()
data_collector = models.CharField(max_length=50)
Essentially, I just want to do this, but it won't work because commonInfo has a user defined primary key
commonInfo_form(request.POST or None).is_valid()
Since I am updating, I am overriding date and data_collector, but not mothers_id. So I would want to do something like this, but this specific code is not working
obj = commonInfo.objects.get(pk=commonInfo_id)
form = commonInfo_form(request.POST)
date = form.cleaned_data['data_collector'] #this line is not working
data_collector = form.cleaned_data['data_collector'] #this line is not working
obj.update(**{'date':date, 'data_collector':data_collector})
any ideas? I feel like it is just those two lines that I need to fix. Or if there is a more pythonic way or built method in Django?
Just validate with isinstance. so like,
if isinstance(request.POST['date'], datetime.date) and isinstance(request.POST['data_collector'], str):
# you might have to use getattr for request.POST here, I'm not sure
# and request.POST['date'] would have to be converted from a string to datetime.date I think
date = request.POST['date']
data_collector = request.POST['data_collector']
obj.update(**{'date':date, 'data_collector':data_collector})
The process for adding a record from a form is different from updating an existing instance. All you need to do differently is indicate which instance to bind the form to when you create it, ex:
obj = commonInfo.objects.get(pk=commonInfo_id)
form = commonInfo_form(request.POST, instance=obj)

update django choice field with database results

I am developing an application using django where the UI needs to be updated when user interacts with it. For instance I have a Drop down field where the user selects a drink and submits it then based on that a dropdown with the places that drink is available, price and quantity at each place needs to be displayed. The user will then further submit the form for second process.
From my understanding the Forms in django are pre-defined and I am not able to think of a way using which I could achieve this.
What I could come up was defining a regular form class
class dform(forms.Form):
SOURCES_CHOICES = (
(A, 'A'),
(E, 'E'),
)
drink = forms.ChoiceField(choices = SOURCES_CHOICES)
location = forms.ChoiceField(choices = **GET THIS FROM DATABASE**)
quantity = forms.ChoiceField(choices = **GET THIS FROM DATABASE**)
.
.
.
My view is like,
def getdrink():
if request.method == 'POST':
#code for handling form
drink = dform.cleaned_data['drink']
#code to get values from database
I have no idea how to generate or populate or append the values i get from the database to the choicefield in my form. I did try looking up on SO but none of the solutions here explained properly how to do it. Also, due to certain requirements I am not using the models. So my database is not at all related to the models.
I am at a total loss Please help me out
class MyForm(forms.Form):
my_choice_field = forms.ChoiceField(choices=MY_CHOICES)
So if you want the values to be dynamic(or dependent of some logic) you can simply modify your code to something like this:
either
def get_my_choices():
# you place some logic here
return choices_list
class MyForm(forms.Form):
my_choice_field = forms.ChoiceField(choices=get_my_choices())
or
User_list = [ #place logic here]
class MyForm(forms.Form):
my_choice_field = forms.ChoiceField(choices=get_my_choices())
but once database value is updated, new data value will be popoulated only on restart of server.
So write a function like this in forms:
class MyForm(forms.Form):
def __init__(self, *args, **kwargs):
super(MyForm, self).__init__(*args, **kwargs)
self.fields['my_choice_field'] = forms.ChoiceField( choices=get_my_choices() )
or in place of the get_my_choices u can ad the USER_LIST too.
If you have models for location and quantity, a ModelChoiceField should work:
class dform(forms.Form):
location = forms.ModelChoiceField(queryset = Location.objects.all())
Otherwise, you'll need to query the database directly, for example:
class dform(forms.Form):
location = forms.ChoiceField(choices = get_location_choices())
# elsewhere
from django.db import connection
def get_location_choices():
cursor = connection.cursor()
cursor.execute("select location_id, name from location_table")
return cursor.fetchall()
The SQL query to use here depends on your database engine and table schema.
I think that, based on my understanding of your question, the best solution would be to include JSON objects with your form and load these using jQuery instead of submitting the form over and over. Included in your form, you should add something like:
class MyForm(forms.Form):
CHOICE_DICT = {
'choice_1': [
'option_1',
'option_2',
],
etc...
Then you should include form.CHOICE_DICT in your context, load that with jQuery, and render it depending on changes to other fields.

Multiple Form with Single Submit Button

I'm currently working with django project. I had to filter the data store on the database based on the user input on form (at template) as looked below.
On form user either enter value or leave it blank. So what I have to do is first find the (valid) user input and then fire appropriate query to display data as user input in the form. So final result should be displayed on table at template.
As I'm new to django, how should I have to pass the data and fire query to represent data at multiple field. As help or link related to these type problem are expected. ( I just able to filter from the database with only one form and had no concept to solve this.)
Model of my temp project is as below.
class exReporter(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
email = models.EmailField()
gender = models.CharField(max_length=1)
age = models.IntegerField()
label = models.IntegerField()
There are a number of approaches you can take, but here is one solution you can use that involves chaining together the appropriate filters based on the form's posted data:
*Note: To conform to Python's naming convention, rename exReporter class to ExReporter.
# views.py
def process_ex_reporter_form(request):
if request.method == "POST":
# ExReporterForm implementation details not included.
ex_reporter_form = ExReporterForm(request.POST)
if ex_reporter_form.is_valid():
# If form field has no data, cleaned data should be None.
gender = ex_reporter_form.cleaned_data['gender']
age_start = ex_reporter_form.cleaned_data['age_start']
age_end = ex_reporter_form.cleaned_data['age_end']
aggregation_group = ex_reporter_form.cleaned_data['aggregation_group']
aggregation_id = ex_reporter_form.cleaned_data['aggregation_id']
ex_reporters = ExReporter.objects.get_ex_reporters(gender, age_start,
age_end, aggregation_group, aggregation_id)
else:
# Pass back form for correction.
pass
else:
# Pass new form to user.
pass
# models.py
class ExReporterManager(models.Manager):
def get_ex_reporters(self, gender, age_start, age_end, aggregation_group,
aggregation_id):
ex_reporters = super(ExReporterManager, self).get_query_set().all()
# Even though the filters are being applied in separate statements,
# database will only be hit once.
if ex_reporters:
if gender:
ex_reporters = ex_reporters.filter(gender=gender)
if age_start:
ex_reporters = ex_reporters.filter(age__gt=age_start)
if age_end:
ex_reporters = ex_reporters.filter(age__lt=age_end)
# Apply further filter logic for aggregation types supported.
return ex_reporters