RoadtripView.put() missing 1 required positional argument: 'pk' - python

I will try to explain my problem in English, because in fact I speak rather French.
I have a little problem and it's been 5 hours now that I can't solve it. I wrote three functions GET, POST and PUT. the first two work well but the PUT has a problem. I am looking to update my Roadtrip table. I send you my codes
# Research for Roadtrip class RoadtripView(CRUDView):
queryset = Roadtrip.objects.all().order_by("-id")
serializer_class=RoadtripSerializers
filter_backends = [DjangoFilterBackend]
filterset_fields = ['cfrom','gto','date']
# Get
def get(self,request,id=None):
if id:
return self.retrieve(request)
else:
return self.list(request)
# Post
def post(self, request, *args, **kwargs):
RoadtripSerializers.Meta.depth = 0
data = request.data
wrappers = super().create(request, *args, **kwargs)
RoadtripSerializers.Meta.depth = 1
return wrappers
# Update
def put(self,request,id,pk,*args,**kwargs):
kwargs['pk'] = self.request.id
RoadtripSerializers.Meta.depth = 0
user = request.user
if user != None:
data = request.data
roadid = Roadtrip.objects.get(id=pk)
submit = super().update(request, pk, *args, **kwargs)
return submits
My Model:
class Roadtrip(models.Model):
user = models.ForeignKey(User,on_delete=models.CASCADE, blank=True, null=True)
cfrom = models.CharField(max_length=200, blank=True,)
gto = models.CharField(max_length=200, blank=True,)
date= models.DateField(blank=True, null=True)
frontsits = models.CharField(max_length=200,blank=True,)
backsits = models.CharField(max_length=200, blank=True,)
hour = models.CharField(max_length=200, blank=True,)
created_at = models.DateField(auto_now_add=True)
def __str__(self):
return f"coming_from=={self.cfrom}<==>going_to:{self.gto}==Date=={self.date}==Hour=={self.hour}"
My URL
urlpatterns = [
path("", include(route.urls)),
path("roadtrip/",RoadtripView.as_view(),name="roadtrip"),
path("roadtrip/<int:id>/",RoadtripView.as_view(),name="roadtripdetal"),
path("booking/<int:id>",BookingView.as_view(),name="booking"),
path("booking/",BookingView.as_view(),name="booking"),
# path("contact/",ContactView.as_view(),name="contact"),
# path("contact/<int:id>",ContactView.as_view(),name="contact"),
path("payment/",PaymentView.as_view(),name="payment"),
path("addtobooking/",addtobooking.as_view(),name="addtobooking"),
]
Error on Swagger doc :
enter image description here

Change
def put(self,request,id,pk,*args,**kwargs):
to
def put(self,request,id,*args,**kwargs): # remove pk
I also suggest that you change id to pk everywhere.

Related

Django import-export with FK constraint

I have been attempting to import data into my Django project using Django import-export. I have two models Ap and Job, Job has a FK relationship with Ap. Using the Admin, I can select the file and the type, CSV. So far my program seems to run, but gets hung up on the FK. I'm close, something is off and causing the import script to fail.
Models.py
class Ap(models.Model):
line_num = models.IntegerField()
vh = models.IntegerField()
vz = models.IntegerField()
status = models.CharField(
choices=statuses, default="select", max_length=40)
classified = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Job(models.Model):
aplink = models.ForeignKey(Ap, related_name=(
"job2ap"), on_delete=models.CASCADE)
job_num = models.IntegerField()
description = models.CharField(max_length=200)
category = models.CharField(
choices=categories, default="select", max_length=40)
status = models.CharField(
choices=statuses, default="select", max_length=40)
dcma = models.BooleanField(default=False),
due_date = models.DateField(blank=True),
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
views.py
class ImportView(View):
def get(self, request):
form = ImportForm()
return render(request, 'importdata.html', {'form': form})
def post(self, request):
form = ImportForm(request.POST, request.FILES)
job_resource = JobResource()
data_set = Dataset()
if form.is_valid():
file = request.FILES['import_file']
imported_data = data_set.load(file.read())
result = job_resource.import_data(
data_set, dry_run=True) # Test the data import
if not result.has_errors():
job_resource.import_data(
data_set, dry_run=False) # Actually import now
else:
form = ImportForm()
return render(request, 'importdata.html', {'form': form})
resource.py
class CharRequiredWidget(widgets.CharWidget):
def clean(self, value, row=None, *args, **kwargs):
val = super().clean(value)
if val:
return val
else:
raise ValueError('this field is required')
class ForeignkeyRequiredWidget(widgets.ForeignKeyWidget):
def clean(self, value, row=None, *args, **kwargs):
if value:
print(self.field, value)
return self.get_queryset(value, row, *args, **kwargs).get(**{self.field: value})
else:
raise ValueError(self.field + " required")
class JobResource(resources.ModelResource):
aplink = fields.Field(column_name='aplink', attribute='aplink', widget=ForeignkeyRequiredWidget(Ap,'id'),
saves_null_values=False)
job_num = fields.Field(saves_null_values=False, column_name='job_num', attribute='job_num',
widget=widgets.IntegerWidget())
description = fields.Field(column_name='description', attribute='description', saves_null_values=False,
widget=CharRequiredWidget())
class Meta:
model = Job
fields = ('aplink', 'job_num', 'description',)
clean_model_instances=True
admin.py
class JobResource(resources.ModelResource):
class Meta:
model=Job
fields=('aplink','job_num','description',)
class JobAdmin(ImportExportModelAdmin):
resource_class = JobResource
admin.site.register(Job, JobAdmin)
CSV file, data to import. I have tried leaving the first column empty, as will as putting the Id of the only Ap stored in the table ie 1. I have also tried hard coding the line_num, which is 1200 the first column as well.
CSV file for importing data:
Date importing errors:
In your resources, while defining fields, you need to include id field in the list. So change JobResource to the following:
class JobResource(resources.ModelResource):
class Meta:
model = Job
fields = ('id', 'aplink', 'job_num', 'description')
If you have defined a custom id field, then you will need to provide:
import_id_fields = ('your_id_field')

Unable to POST the data using rest Django - NOT NULL constraint failed: author_id

I have the following error, and I guess the problem with how can I add the author id to the post automatically.
And also I tried to add null=True
author = models.ForeignKey(User, null=True, blank=True)
The error disappeared, but unfortunately, the author's id is still null.
IntegrityError at /auctions/api/addAuction/
NOT NULL constraint failed: auctions_auction.author_id
Request Method: POST
Request URL: http://127.0.0.1:8000/auctions/api/addAuction/
Django Version: 3.1.5
Exception Type: IntegrityError
Exception Value:
NOT NULL constraint failed: auctions_auction.author_id
/auctions/api/serializers.py
class AddAuctionsSerializer(serializers.ModelSerializer):
print("AddA uctionsSerializer Function call")
class Meta:
model = Auction
# Get the current user from request context
def validate_author(self, value):
return self.context['request'].user
author_id = serializers.Field(source='author.id')
fields = ["title", "desc", "image","location","min_value","date_added","author_id"]
read_only_fields = ('author','id','author_id','author.id')
/auctions/api/view.py
class addAuction(APIView):
#permission_classes = [permissions.IsAuthenticated]
#authentication_classes = [SessionAuthentication, BasicAuthentication]
def pre_save(self, obj):
obj.owner = self.request.user
def post(self, request, format=None):
auction = Auction()
auction.author = request.user
serializer = AddAuctionsSerializer(data=request.data)
print(serializer)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
/auctions/api/url.py
path('addAuction/', addAuction.as_view()),
/auctions/model.py
class Auction(models.Model):
location = LocationField()
author = models.ForeignKey(User, on_delete=models.CASCADE,null=False)
# author = models.ForeignKey(User, null=True, blank=True)
title = models.CharField(max_length=300)
desc = models.CharField(max_length=2000, blank=True)
image = models.ImageField(upload_to='auction_images/', blank=True, default = 'auction_images/default/default.svg')
min_value = models.IntegerField()
#date_added = models.DateTimeField()
date_added = models.DateTimeField(auto_now_add=True)
is_active = models.BooleanField(default=True)
winner = models.ForeignKey(User, on_delete=models.SET("(deleted)"),
blank=True,
null=True,
related_name="auction_winner",
related_query_name="auction_winner")
final_value = models.IntegerField(blank=True, null=True)
def resolve(self):
if self.is_active:
# If expired
if self.has_expired():
# Define winner
highest_bid = Bid.objects.filter(auction=self).order_by('-amount').order_by('date').first()
if highest_bid:
self.winner = highest_bid.bidder
self.final_value = highest_bid.amount
self.is_active = False
self.save()
# Helper function that determines if the auction has expired
def has_expired(self):
now = datetime.now(timezone.utc)
expiration = self.date_added + timedelta(minutes=AUCTION_DURATION)
if now > expiration:
return True
else:
return False
# Returns the ceiling of remaining_time in minutes
#property
def remaining_minutes(self):
if self.is_active:
now = datetime.now(timezone.utc)
expiration = self.date_added + timedelta(minutes=AUCTION_DURATION)
minutes_remaining = ceil((expiration - now).total_seconds() / 60)
return(minutes_remaining)
else:
return(0)
Try using SlugRelatedField instead of Field.
Like so:
class AddAuctionsSerializer(serializers.ModelSerializer):
# instead of this:
# author_id = serializers.Field(source='author.id')
# do this:
author = serializers.SlugRelatedField(queryset=User.objects.all(), slug_field='id', write_only=True)
class Meta:
model = Auction
fields = ["title", "desc", "image","location","min_value","date_added","author"]
# don't put 'author_id' in read_only, because creating is "writing"
# also note that 'author.id' is invalid field
# read_only_fields = ('author','id','author_id','author.id')
read_only_fields = ('id')
# Get the current user from request context
def validate_author(self, value):
return self.context['request'].user
I had the same problem.
You can solve it by overwriting the create method of AddAuctionsSerializer and manually defining instance.author, or by passing the parameter author = request.user, to the save method of AddAuctionsSerializer,

Django model foreignkey queries

So i have this two models in django:
class Course(models.Model):
def get_image_path(self, filename):
return os.path.join('courses', str(self.slug), filename)
def __str__(self):
return self.name
def save(self, *args, **kwargs):
self.slug = slugify(self.name)
super(Course, self).save(*args, **kwargs)
name = models.CharField(max_length=255, verbose_name="Nombre")
description = models.CharField(max_length=255, verbose_name="DescripciĆ³n")
price = models.DecimalField(max_digits=12,decimal_places=2, verbose_name="Precio")
slug = models.SlugField(blank=True, max_length=255)
icon_img = models.ImageField(upload_to=get_image_path, blank=True, null=True, verbose_name="Imagen")
background_color = ColorField(default="#026085")
class Meta:
verbose_name = "curso"
verbose_name_plural = "cursos"
class UserCourse(models.Model):
user = models.ForeignKey(User)
course = models.ForeignKey(Course)
So whenever a user "buys" a course, it is stored in UserCourse. I have a view where the system shows a list of all the courses the user has bought. This is the view code:
def user_course_list_view(request, username):
context_dict = {}
try:
user_courses = UserCourse.objects.filter(user=request.user).course_set
context_dict['courses'] = user_courses
context_dict['heading'] = "Mis cursos"
except:
context_dict['courses'] = None
context_dict['heading'] = "Mis cursos wey"
return render(request, 'courses/course_list.html', context=context_dict)
I dont know where is the error and I cant seem to catch the exception (im using django with docker)
tl;dr
Something like this should work.
usercourse_objects = UserCourse.objects.filter(user=request.user).select_related('course')
user_courses = [x.course for x in usercourse_objects]
Explanation
There are multiple ways to do this, but one way would be to first get all the UserCourse objects for the current user:
usercourse_objects = UserCourse.objects.filter(user=request.user)
Then, for each UserCourse object, get the related Course:
user_courses = [x.course for x in usercourse_objects]
Now, the second line causes N database queries (one for each time we follow the course foreign key relation. To prevent this, the first line can be changed to:
usercourse_objects = UserCourse.objects.filter(user=request.user).select_related('course')
This pre-populates the course attribute of the UserCourse objects. More info about select_related() can be found here.

How to add new data from ebay to database in Django?

I am using python ebay-sdk library for connection to ebay api.
I want to get some cases from ebay api and save it to the database.
I have one app and models like this:
class Case(models.Model):
# case is not necessarily a listing (often O2M)
STATUS = Choices('new', 'cancelled', 'active', 'taken_down', 'archived')
name = models.CharField(max_length=512)
when_created = models.DateTimeField(default=now, blank=True)
user = models.ForeignKey(User)
make = models.ForeignKey(Make)
status = StatusField(default=STATUS.new)
platform = models.ForeignKey(Platform, on_delete=models.CASCADE)
listing_id = models.CharField(max_length=64)
listing_owner = models.CharField(max_length=128)
url = models.CharField(max_length=512)
price = models.FloatField(blank=True, null=True)
# for now currency as char is ok.
currency = models.CharField(max_length=3, default='USD')
quantity = models.IntegerField(default=1)
when_listing_started = models.DateTimeField(blank=True, null=True)
when_listing_ends = models.DateTimeField(blank=True, null=True)
valid_days = models.IntegerField(blank=True, null=True)
objects = models.Manager.from_queryset(CaseQueryset)()
def __str__(self):
return self.name
#property
def days_valid(self):
created = self.when_created.replace(tzinfo=None)
now = datetime.datetime.utcnow().replace(tzinfo=None)
datetime.timedelta(6, 1)
return (now - created).days
def handle_sent_report(self):
self._set_active_state()
def handle_cancel(self):
self._set_cancelled_state()
def _set_active_state(self):
if self.status != Case.STATUS.new:
raise InvalidCaseStatus
self.status = Case.STATUS.active
self.save()
def _set_cancelled_state(self):
if self.status not in (Case.STATUS.new, Case.STATUS.active):
raise InvalidCaseStatus
self.status = Case.STATUS.cancelled
self.save()
And I created other app ebay-finder and ebay_find.py to find cars in eBay:
from ebaysdk.finding import Connection as Finding
from django.db import models
from cases.models import Case
from trademarks.models import Make
def ebay_find():
pass
api = Finding(domain='svcs.sandbox.ebay.com', appid="MY_EBAY_APP_ID", config_file=None)
response = api.execute('findItemsAdvanced', {'keywords': 'Cadillac'})
items = response.dict()
items_list = items['searchResult'].get('item')
ebay_cases = []
for item in items_list:
new_case = Case.objects.create(
name=item['title'],
platform="Ebay",
listing_id=car["model"],
url=item['viewItemURL'],
price=item['sellingStatus']['currentPrice']['value'],
currency=item['sellingStatus']['currentPrice']['_currencyId']
)
new_case.save()
I'm confused how to add this data from items_list to my database like in Case. I must take all the same fields like in Case? Can I have some fields default on create object?
If your want your data to be saved with the least hassle, then yes, use the same field-names.
You have an example of a model field with a default in your own code:
currency = models.CharField(max_length=3, default='USD')
You could also override your model's save() method:
def save(self, *args, **kwargs):
super(Case, self).save(*args, **kwargs)
if not self.when_listing_started:
self.when_listing_started = datetime.datetime.now()
super(Case, self).save(*args, **kwargs)

Create lists in ListView from model field in django

I would like to use ListView to generate lists of degrees by school and state. For example, I would want to use to the degree_awarded field in the Program model to make a list of "Schools in Pennsylvania Where You Can Get A Bachelor Degree."
Models
class State(models.Model):
state_name = models.CharField(max_length=20, default='')
state_slug = models.SlugField()
def __str__(self):
return self.state_slug
class City(models.Model):
city_name = models.CharField(max_length=55, default='')
city_slug = models.SlugField()
state = models.ForeignKey(State, null=True)
def __str__(self):
return self.city_slug
class School(models.Model):
school_name = models.CharField(max_length=55, default='')
school_slug = models.SlugField()
city = models.ForeignKey(City, null=True)
def __str__(self):
return self.school_slug
def sorted_programs(self):
return self.program_set.all().order_by('program_name')
class Program(models.Model):
program_name = models.CharField(max_length=100, default='')
program_slug = models.SlugField(max_length=100, default='')
school = models.ForeignKey(School, null=True)
degree_awarded = models.CharField(max_length=10, default='')
def __str__(self):
return self.program_slug
Views
class SchoolIndexView(ListView):
model = State
def get_context_data(self, **kwargs):
context = super(SchoolIndexView, self).get_context_data(**kwargs)
context['state_list'] = State.objects.all().order_by('state_name')
return context
class ProgramInSchoolView(DetailView):
model = School
template = 'school_detail.html'
def get_object(self):
school_slug = School.objects.get(
school_slug=self.kwargs.get('school_slug')
)
return school_slug
def get_context_data(self, **kwargs):
context = super(ProgramInSchoolView, self).get_context_data(**kwargs)
context['school'] = self.object
context['program_list'] = self.object.program_set.all().order_by('program_name')
return context
class ProgramView(DetailView):
model = Program
template = 'program_detail.html'
def get_object(self):
program_slug = Program.objects.get(
program_slug=self.kwargs.get('program_slug')
)
return program_slug
def get_context_data(self, **kwargs):
context = super(ProgramView, self).get_context_data(**kwargs)
context['program'] = self.object
context['program_classes'] = self.object.classes_set.all().order_by('class_number')
return context
class DegreeView(ListView):
model = Program
template = 'degree_list.html'
def get_context_data(self, **kwargs):
context = super(DegreeView, self).get_context_data(**kwargs)
context['state_for_degree'] = State.objects.get(state_slug=self.kwargs.get('state_slug'))
context['city_for_degree'] = City.objects.get(city_name=self.kwargs.get('city_name'))
context['school_for_degree'] = School.objects.get(school_slug=self.kwargs.get('school_slug'))
context['degree_by_state'] = Program.objects.get(degree_awarded=self.kwargs.get('degree_awarded')).filter(school_slug=school_slug).filter(city_slug=city_slug).filter(state_slug=state_slug).order_by('city_name')
return context
Urls
url(r'^(?P<state_slug>[\w-]+)/$', CityInStateView.as_view(), name='state_detail'),
url(r'^(?P<state_slug>[\w-]+)/(?P<school_slug>[\w-]+)/$', ProgramInSchoolView.as_view(), name='school_detail'),
url(r'^(?P<state_slug>[\w-]+)/(?P<school_slug>[\w-]+)/(?P<program_slug>[\w-]+)/$', ProgramView.as_view(), name='program_detail'),
url(r'^(?P<state_slug<[\w-]+)/(?P<program_slug>[\w-]+)/$', DegreeView.as_view(), name='degree_list'),
I cannot figure out how to write the view and url routing so that I can use the information I already have in the degree_awarded field of the Program model to generate a list.
Can someone please point me in the right direction?
Thank you.
Edit: I've added the relevant model(s) that I left out before. I wanted to be concise. I've also added in the last filter that I tried. It is still not producing the degree lists sorted by state.
I don't think you need all that code in the get_context_data method. You should customize the list of objects to display in the get_queryset method.
class DegreeView(ListView):
model = Program
template = 'degree_list.html'
def get_queryset(self):
queryset = super(DegreeView, self).get_queryset()
# batchelors degrees only
queryset = queryset.filter(program_slug=self.kwargs['program_slug'])
# filter by state
queryset = queryset.filter(school__city__state__slug=self.kwargs['state_slug'])
return queryset
See the docs on lookups that span multiple relationships to explain the school__city__state__slug filter.
Then in your template, you can loop through the programs, for example:
{% for program in object_list %}
{{ program.degree_awarded %}

Categories

Resources