how to sort an array of object in django? - python

I am making an project with python and django about github profile. I already successful call user github API and it give me like a lot of repos from that user and I want to display like 8 of them and sorted by stars or forks or size of that repo. How can I do that?
Here's an image of my page:
Here is my views.py:
def user(req, username):
username = str.lower(username)
# Get User Info
with urlopen(f'https://api.github.com/users/{username}') as response:
source = response.read()
data = json.loads(source)
# Get Limit Call API
with urlopen(f'https://api.github.com/rate_limit') as response:
source = response.read()
limit_data = json.loads(source)
# Get User Repo Info
with urlopen(f'https://api.github.com/users/{username}/repos') as response:
source = response.read()
user_repos = json.loads(source)
def sort_user_repo_by_stars(user_repos):
return user_repos['stargazers_count']
user_repos.sort(key=sort_user_repo_by_stars, reverse=True)
created_at = data['created_at']
created_at = datetime.datetime.strptime(created_at, "%Y-%m-%dT%H:%M:%SZ")
created_at = created_at.strftime("%B %d, %Y")
context = {
'username': username,
'data': data,
'created_at': created_at,
'limit_data': limit_data,
'user_repos': user_repos,
}
return render(req, 'user.html', context)
and here is my template user.html:
<div class="repos">
<div class="top-repo">
<label for="top-repos" class="col-sm-3 col-form-label">Top Repos <span>by </span></label>
<select class="custom-select bg-light text-primary" name="pick">
<option selected="stars">stars</option>
<option value="forks">forks</option>
<option value="size">size</option>
</select>
</div>
<div class="repo-info">
{% for repo in user_repos %}
<div class="card-deck">
<div class="card shadow">
<div class="card-body">
<h4 class="card-title">{{repo.name}}</h4>
<p class="card-text clearfix">
<i class="fas fa-circle"></i> {{repo.language}}
<i class="fas fa-star"></i> {{repo.stargazers_count}}
<i class="fal fa-code-branch"></i> {{repo.forks}}
<span class="float-right">{{repo.size}} KB</span>
</p>
</div>
</div>
</div>
{% endfor %}
</div>
</div>

If you only want an array of 8 elements then you can use a slice operator on your list.
context = {
"username": username,
"data": data,
"created_at": created_at,
"limit_data": limit_data,
"user_repos": user_repos[:8],
}

Related

Unable to Deploy Django in Heroku

I am unable to deploy django in Heroku. I think the problem lies with Ajax because all of the pages seems to render in heroku.
Error that I got is:
InvalidCursorName at /incidentReport/general
cursor "_django_curs_140297876031040_sync_1" does not exist
During handling of the above exception (relation "incidentreport_accidentcausation" does not exist LINE 1: ...cidentreport_accidentcausation"."updated_at" FROM "incidentr... ^ ), another exception occurred:
Thank you
HTML
<!-- Page Content -->
<div class="container-fluid">
<!-- Page Title -->
<div class="d-flex bd-highlight">
<div class="pg-title p-2 flex-grow-1 bd-highlight">
<h4>Incident Report</h4>
</div>
</div>
<!-- User Report Table -->
<div class="card shadow mb-5 d-flex ">
<!-- Top Pagination -->
<div class="card-header py-3">
<ul class="nav nav-tabs">
<li class="nav-item">
<a class="nav-link active" href="{% url 'incident_report_general' %}">General</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{% url 'incident_report_people' %}">People</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{% url 'incident_report_vehicle' %}">Vehicle</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{% url 'incident_report_media' %}">Media</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{% url 'incident_report_remarks' %}">Remarks</a>
</li>
</ul>
</div>
<div class="card-body">
<div class="table-responsive">
<table>
<form id="form_incidentgeneral" action="{% url 'incident_report_general' %}" enctype="multipart/form-data" method="post" data-acc-url="{% url 'ajax_load_accident' %}">
<div class="form-row">
<div class="form-group col-md-6">
<label for="inputEmail4">Date</label>
{{user_report_form.date}}
</div>
<div class="form-group col-md-6">
<label for="inputPassword4">Time</label>
{{user_report_form.time}}
</div>
</div>
<hr>
<div class="form-row">
<div class="form-group col-md-12">
<label for="inputAddress">Street Address</label>
{{user_report_form.location}}
</div>
</div>
<hr>
<div class="form-row">
<div class="form-group col-md-6">
<label for="inputWeather">Weather</label>
{{inc_gen_form.weather}}
</div>
<div class="form-group col-md-6">
<label for="inputLight">Light</label>
{{inc_gen_form.light}}
</div>
</div>
<!-- ================================= -->
<hr>
<div class="form-row">
<div class="form-group col-md-12">
<label for="inputSeverity">Severity</label>
{{inc_gen_form.severity}}
</div>
</div>
<div class="form-row">
<div class="form-group col-md-6">
<label for="inputAccident">Accident Factor</label>
{{inc_gen_form.accident_factor}}
</div>
<div class="form-group col-md-6">
<label for="inputAccident">Accident Factor Sub Category</label>
{{inc_gen_form.accident_subcategory}}
</div>
</div>
<div class="form-row">
<div class="form-group col-md-6">
<label for="inputAccident">Collision Type</label>
{{inc_gen_form.collision_type}}
</div>
<div class="form-group col-md-6">
<label for="inputAccident">Collision Sub Category</label>
{{inc_gen_form.collision_subcategory}}
</div>
</div>
<!-- ================================= -->
<div class="form-row">
<div class="form-group col-md-6">
<label for="inputCrashType">Crash Type</label>
{{inc_gen_form.crash_type}}
</div>
<div class="form-group col-md-6">
<label for="inputMovement">Movement Code</label>
{{ inc_gen_form.movement_code }}
</div>
</div>
<!-- ================================= -->
<br>
<div class="modal-footer mb-3">
<input type="button" class="btn btn-secondary" data-dismiss="modal"
value="Clear">
<input type="submit" class="btn btn-primary" value="Save">
</div>
</form>
</table>
</div>
</div>
</div>
<!-- End of User Report Table -->
</div>
<!-- End of Page Content -->
AJAX
<script>
$("#id_accident_factor").change(function () {
const url = $("#form_incidentgeneral").attr("data-acc-url"); // get the url of the `load_cities` view
const accidentId = $(this).val(); // get the selected country ID from the HTML input
$.ajax({ // initialize an AJAX request
url: url, // set the url of the request (= /persons/ajax/load-cities/ )
data: {
'accident_factor_id': accidentId // add the country id to the GET parameters
},
success: function (data) {
//console.log(data) // `data` is the return of the `load_cities` view function
$("#id_accident_subcategory").html(data); // replace the contents of the city input with the data that came from the server
let html_data = '<option value="">---------</option>';
data.forEach(function (accident_subcategory) {
html_data += `<option value="${accident_subcategory.id}">${accident_subcategory.sub_category}</option>`
});
console.log(html_data);
$("#id_accident_subcategory").html(html_data);
}
});
});
$("#id_collision_type").change(function () {
const url = $("#form_incidentgeneral").attr("data-acc-url"); // get the url of the `load_cities` view
const collisionId = $(this).val(); // get the selected country ID from the HTML input
$.ajax({ // initialize an AJAX request
url: url, // set the url of the request (= /persons/ajax/load-cities/ )
data: {
'collision_type_id': collisionId // add the country id to the GET parameters
},
success: function (data) {
//console.log(data) // `data` is the return of the `load_cities` view function
$("#id_collision_subcategory").html(data); // replace the contents of the city input with the data that came from the server
let html_data = '<option value="">---------</option>';
data.forEach(function (collision_subcategory) {
html_data += `<option value="${collision_subcategory.id}">${collision_subcategory.sub_category}</option>`
});
console.log(html_data);
$("#id_collision_subcategory").html(html_data);
}
});
});
</script>
Dropdown HTML
<option value="">---------</option>
{% for accsubcategory in acc_subcat %}
<option value="{{ accsubcategory.pk }}">{{ accsubcategory.sub_category }}</option>
{% endfor %}
{% for colsubcategory in col_subcat %}
<option value="{{ colsubcategory.pk }}">{{ colsubcategory.sub_category }}</option>
{% endfor %}
Views
def incident_report_general(request):
if request.method == 'POST':
user_report_form = UserReportForm(request.POST, request.FILES)
inc_gen_form = IncidentGeneralForm(request.POST, request.FILES)
else:
user_report_form = UserReportForm()
inc_gen_form = IncidentGeneralForm()
context = {
'user_report_form': user_report_form,
'inc_gen_form': inc_gen_form,
}
return render(request, 'pages/incident_report.html', context)
def load_accident(request):
accident_factor_id = request.GET.get('accident_factor_id')
collision_type_id = request.GET.get('collision_type_id')
acc_subcat = AccidentCausationSub.objects.filter(accident_factor_id=accident_factor_id).all()
col_subcat = CollisionTypeSub.objects.filter(collision_type_id=collision_type_id).all()
context = {
'acc_subcat': acc_subcat,
'col_subcat': col_subcat
}
return render(request, 'incident/acc_sub_dropdown_list_options.html', context)
Form
class IncidentGeneralForm(forms.ModelForm):
class Meta:
model = IncidentGeneral
fields = '__all__'
def __init__(self, *args, **kwargs):
super(IncidentGeneralForm, self).__init__(*args, **kwargs)
self.fields['accident_factor'].widget.attrs['class'] = 'form-control'
self.fields['accident_subcategory'].widget.attrs['class'] = 'form-control'
self.fields['collision_type'].widget.attrs['class'] = 'form-control'
self.fields['collision_subcategory'].widget.attrs['class'] = 'form-control'
self.fields['weather'].widget.attrs['class'] = 'form-control'
self.fields['light'].widget.attrs['class'] = 'form-control'
self.fields['severity'].widget.attrs['class'] = 'form-control'
self.fields['crash_type'].widget.attrs['class'] = 'form-control'
self.fields['movement_code'].widget.attrs['class'] = 'form-control'
self.fields['accident_subcategory'].queryset = AccidentCausationSub.objects.none()
self.fields['collision_subcategory'].queryset = CollisionTypeSub.objects.none()
if 'accident_factor' in self.data:
try:
accident_factor_id = int(self.data.get('accident_factor'))
self.fields['accident_subcategory'].queryset = AccidentCausationSub.objects.filter(accident_factor_id=accident_factor_id).order_by('accident_factor')
except (ValueError, TypeError):
pass # invalid input from the client; ignore and fallback to empty City queryset
elif self.instance.pk:
self.fields['accident_subcategory'].queryset = self.instance.accident_factor.accident_subcategory_set.order_by('subcategory')
if 'collision_type' in self.data:
try:
collision_type_id = int(self.data.get('collision_type'))
self.fields['collision_subcategory'].queryset = CollisionTypeSub.objects.filter(collision_type_id=collision_type_id).order_by('collision_type')
except (ValueError, TypeError):
pass # invalid input from the client; ignore and fallback to empty City queryset
elif self.instance.pk:
self.fields['collision_subcategory'].queryset = self.instance.collision_type.collision_subcategory_set.order_by('subcategory')

how to pass django view data in js to get product id accordingly

the problems is i have passing data from view to product template , when i click add to cart i have to get product id accordingly using js how can i do this inside templates it work but when i apply inside script it doesn't work is there any method to access / get data
my views.py
def product(request):
productbyid = None
categories = ProductCategory.get_all_categories()
products = TopList.get_all_products()
categoryID = request.GET.get('category')
if categoryID:
productbyid =TopList.objects.filter(category=categoryID)
else:
productbyid = TopList.get_all_products()
data = {}
data['categories']:categories
data['productbyid'] =productbyid
data['products'] = products
data['categories'] =categories
return render(request,'product.html',data)
my product.html
% for pbyid in productbyid %}
<div class="card card_body m-2 p-0 container" id='{{pbyid.id}}'>
<div>
<div>
<div class='imagestyle' ><img class="card-img-top " src="{{pbyid.image}}"width="500" height="200" alt="Card image cap "></div>
<span class="top-left">{{pbyid.discountpercentage}}% off</span>
</div>
<div class="card-body">
<h5 class="card-title cardtitle">{{pbyid.title}}</h5>
<div><p class="carddesccrip">{{pbyid.desc}} </p></div>
<div class='pricce_card'>
<span class='price'> <b>M.R.P</b> <strike class='carddesc'>RS {{pbyid.discountPrice}}</strike></span>
<span class='final_price'><b>RS. {{pbyid.finalprice}}</b></span>
</div>
</div>
<div class="card-body">
{% comment %} /viewpage/{{pbyid.id}} {% endcomment %}
<button href="" class="btn btn-lg btn-block addbtn caddtocart" onclick="myFunction()" > Add to cart {{pbyid.id}}
<i class="fa fa-plus float-right align-center p-2 plusbtn" aria-hidden="true"></i></button>
</div>
</div>
</div>
{% endfor %}
js , my try here i when i click caddtocart btn i have to get product id accordingly but it doesn't work .
<script>
var x = document.getElementsByClassName("caddtocart");
function myFunction() {
d = "{{products}}";
data = parseInt(d);
console.log(data);
}
</script>
you can pass variables from a template to JS like so:
onclick="myfunction({{pbyid.id}})"
this will pass the id to the function for you then in your js you get the parameter like:
myfunction(id){}

Flask sending info with GET when POST specified

I am creating an online bookstore and am having trouble with one specific entry. When a user purchases a book they are able to rate it and this functionality works except for the first book they purchased. The function works with the POST method and the form passes in a book_id and a rating which I then enter into a database using SQLAlchemy. The HTML code to submit the form is as such
<form action="/add_rating" method="POST">
<select name="rating" id="rating">
<option value="1">1</option>
<option value="3">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
</select>
<button class="btn btn-success" id='adding_rating' name="book_id" type="submit" value='{{display_cart[book].book_id}}'>Rating</button>
</form>
As you can see the method is set to POST. The background function/route to enter the rating into the database is as follows:
#app.route('/add_rating',methods=["POST"])
def add_rating():
if "cart" not in session:
flash("There is nothing in your cart.")
return render_template("cart.html", display_cart = {}, total = 0)
dict_of_books = {}
## getting user info
user = User.query.get(session['user_id'])
user_name = user.first_name + ' ' + user.last_name
##Get order history by user_id
order = get_order_history(session['user_id'])
dict_of_books = {}
total_price = 0
for i in range(len(order)):
total_price += order[i].total
book = get_book_by_id(order[i].book_id)
details = {'book_id': order[i].book_id, "title": book.title, "quantity": order[i].quantity, 'total': order[i].total}
dict_of_books[i] = details
book_id = request.form.get('book_id')
ratings = request.form.get('rating')
user_id = session['user_id']
add_rating = create_rating(ratings,book_id,user_id)
return render_template("rating.html", display_cart = dict_of_books, total = total_price, user_info = user_name)
Now when I rate the first book it is sending the information through GET into the URL, but all the other purchases are sending through POST. The output flask/sqlalchemy gives for the first book is "GET /rating?rating=3&book_id=4 HTTP/1.1" 200 - but for the rest of the books it is "POST /add_rating HTTP/1.1" 200 -. The /rating route is basically just getting information about purchased books and displaying to the page and I do not specify GET/POST in the route. In case the route is needed I will post below, but I cant imagine it being of use to this issue.
#app.route('/rating')
def rate_book():
if "cart" not in session:
flash("There is nothing in your cart.")
return render_template("cart.html", display_cart = {}, total = 0)
dict_of_books = {}
## getting user info
user = User.query.get(session['user_id'])
user_name = user.first_name + ' ' + user.last_name
##Get order history by user_id
order = get_order_history(session['user_id'])
dict_of_books = {}
total_price = 0
for i in range(len(order)):
total_price += order[i].total
book = get_book_by_id(order[i].book_id)
details = {'book_id': order[i].book_id, "title": book.title, "quantity": order[i].quantity, 'total': order[i].total}
dict_of_books[i] = details
return render_template("rating.html", display_cart = dict_of_books, total = total_price, user_info = user_name)
I figured out the issue, it seems that I have added a "parent" form tag and within it added another form tag to handle the button press. By changing the first form (one without method="POST") to just a div tag, it fixed the issue.
Example,
Original:
<div class="container h-100">
<div class="row align-items-center h-100">
<div class="col-6 mx-auto">
<div style="display: flex; align-items: center;">
<form>
...
<form action="/add_rating" method="POST">
...
</form>
</div>
</div>
</div>
</div>
To
<div class="container h-100">
<div class="row align-items-center h-100">
<div class="col-6 mx-auto">
<div style="display: flex; align-items: center;">
<div>
...
<form action="/add_rating" method="POST">
...
</div>
</div>
</div>
</div>
</div>

Python Django multiple attributes in search

So I have this search form:
[Doctor][Specialty][City]
This is the form in HTML:
<form data-provide="validation" data-disable="true" class="input-glass mt-7" method='POST' action='annuaire/'>
{% csrf_token %}
<div class="row">
<div class="col-md-4">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="ti-search mt-1"></i></span>
</div>
<input type="text" class="form-control" placeholder="Doctor's Name" name="kw_name">
</div>
</div>
<div class="col-md-4">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="ti-search mt-1"></i></span>
</div>
<select class="form-control" name="kw_specialty">
<option value="" disabled selected>Specialty</option>
{% for spec in specialties %}
<option>{{ spec }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="col-md-4">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="ti-search mt-1"></i></span>
</div>
<select class="form-control" name="kw_city">
<option value="" disabled selected>City</option>
{% for city in cities %}
<option>{{ city }}</option>
{% endfor %}
</select>
</div>
</div>
</div>
<div class="row mt-2">
<div class="col-md-12">
<button class="btn btn-lg btn-block btn-outline-light" type="submit" name="search_btn">Search</button>
</div>
</div>
</form>
Before I talk about my view.py content, I would like to mention my problem first: The search form has many cases, and the users don't have to fill all three filters. But if they leave the text input empty, the results will be ALL. I want the search function to ignore the text field if it's empty (only consider it if it has a value in it). Also, if the 2 dropdowns are Null (or None) the function gives an error. Anyways my desired outcome would be to give 3 different choices to choose from, and if someone uses more than one attributes, they all have to be true, if a selection is empty, it should be ignored.
Here is my views.py file:
def search(request):
val_name = request.POST.get('kw_name')
val_city = request.POST.get('kw_city')
val_specialty = request.POST.get('kw_specialty')
if val_city is None:
val_city = ''
if val_specialty is None:
val_specialty = ''
if 'search_btn' in request.POST:
if val_city is None:
if val_name is not None:
doctors = Doctor.objects.filter(Q(user__first_name__icontains=val_name) |
Q(user__last_name__icontains=val_name) &
Q(specialty__title__icontains=val_specialty))
else:
doctors = Doctor.objects.filter(Q(user__first_name__icontains=val_name) |
Q(user__last_name__icontains=val_name) &
Q(specialty__title__icontains=val_specialty))
elif val_specialty is None:
doctors = Doctor.objects.filter(Q(user__first_name__icontains=val_name) |
Q(user__last_name__icontains=val_name) &
Q(city__title__icontains=val_city))
elif 'closest_btn' in request.POST:
# deleted because not related to the problem.
context = {
'page_title': 'Résultats des médecins',
'doctors': doctors,
}
return render(request, "dashboard/results.html", context)
Thank you for your great help!
PS: I already put some ifs and elses in the view to try to solve the issue but it's still not working. Sometimes it gives me results that don't satisfy any of the search criteria.
I have been able to use user filters successfully by using dictionaries and then unpacking them in the filter() function. For your case, I would try something as follows:
def search(request):
val_name = request.POST.get('kw_name', '')
filters = {
'city__title__icontains': request.POST.get('kw_city'),
'specialty__title__icontains': request.POST.get('kw_specialty')
}
filters = {k: v for k, v in filters.items() if v}
q = Q(user__first_name__icontains=val_name) | Q(user__last_name__icontains=val_name)
doctors = Doctor.objects.filter(q, **filters)
context = {
'page_title': 'Résultats des médecins',
'doctors': doctors,
}
return render(request, "dashboard/results.html", context)

iterate users in friends list over same modal and access database content

I am making a chat box for my website. As per current implementation,i i am iterating over the current friends list and and anchor tag triggers a modal for that particular user. The modal is common for all users as it only changes the data inside.
Now, i have used jquery to fetch the message history ( from model object ) and display is modal body.
I can click on different users and view the messages in their respective models correctly. However, when i try to submit the form to send another message it gets added to the message box of first user. This is happening for all users in the friend list.
How can i trigger the form to post in the model of the correct user.
Template
{% for friend in friends_list %}
<li style="padding:10px">{{friend.to_user.usercreation.fname}} {{friend.to_user.usercreation.lname}} <i style ="color:green;font-size:0.65rem;text-align:justify;float:right;margin-top:8.5px;" class="fa fa-circle" aria-hidden="true"></i></li>
<form action="{% url 'usercreation:addmessage' friend.to_user.usercreation.pk %}" method="post">
{% csrf_token %}
<div class="modal fade" id="chatbox" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header text-center">
<h6 class="modal-title w-100">BlogChat</h6>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<pre><div class="modal-body"></div></pre>
<div class="modal-footer">
<input style="width:330px;height:40px" type="text" name="addmessage" value="" placeholder="Type..">
<button style="float:right;" type="submit" class="btn btn-primary">Send message</button>
</div>
</div>
</div>
</div>
</form>
{% endfor %}
JQUERY:
<script type="text/javascript">
$('#chatbox').on('show.bs.modal', function (event) {
var button = $(event.relatedTarget)
var recipient = button.data('whatever')
attributes
$.ajax({
url: "{% url 'fetcher' %}",
data: {
'search': recipient
},
dataType: 'json',
success: function (data) {
list = data.list;
$('#chatbox').find('.modal-body').text(list)
}
});
var modal = $(this)
modal.find('.modal-title').text('Chat with ' + recipient)
})
</script>
VIEWS:
def fetcher(request):
if request.is_ajax():
name = User.objects.get(username=request.GET.get('search', None))
b = ChatMessage.objects.get(user1 = request.user,user2 = name)
print(b.message)
data = {
'list': b.message,
}
print(data)
return JsonResponse(data)
def addmessage(request,pk):
if request.method=='POST':
print(request.user)
print(User.objects.get(username=UserCreation.objects.get(pk=pk)))
obj = ChatMessage.objects.get(user1 = request.user , user2 = User.objects.get(username=UserCreation.objects.get(pk=pk)) )
obj2 = ChatMessage.objects.get(user2 = request.user , user1 = User.objects.get(username=UserCreation.objects.get(pk=pk)) )
name = request.POST.get('addmessage')
obj.message += ('\n'+str(request.user)+': '+name)
obj2.message += ('\n'+str(request.user)+': '+name)
obj.save()
obj2.save()
return HttpResponseRedirect(reverse('usercreation:profile',args=[request.user.usercreation.pk]))
Models:
class ChatMessage(models.Model):
user1 = models.ForeignKey(User, on_delete=models.CASCADE ,related_name="participant1")
user2 = models.ForeignKey(User, on_delete=models.CASCADE , related_name="participant2")
message = models.TextField(default="")
date = models.DateTimeField(auto_now=True, db_index=True)

Categories

Resources