I'm pretty sure there's a better way to do this:
class PostSerializer(serializers.ModelSerializer):
class Meta:
model = Post
fields = ('category', 'id', 'title', 'image', 'slug', 'author', 'excerpt', 'content', 'status', 'published')
class FrontendPostSerializer(serializers.ModelSerializer):
author = AuthorSerializer(many=False, read_only=True)
category = CategorySerializer(many=False, read_only=True)
class Meta:
model = Post
fields = ('category', 'id', 'title', 'image', 'slug', 'author', 'excerpt', 'content', 'status', 'published')
PostSerializer is gonna look like this
{
"category": 1,
"id": 45,
"title": "Lorem Ipsum - Lorem ipsum dolor sit amet consectetur",
"image": "http://localhost:8000/media/posts/car_SxXcUTV.jpg",
"slug": "lorem-ipsum-lorem-ipsum-dolor-sit-amet-consectetur",
"author": 4,
"excerpt": "Officiis iure rerum voluptates a cumque velit \nquibusdam sed amet tempora. Sit laborum ab, eius fugit doloribus tenetur \nfugiat, temporibus enim commodi iusto libero magni deleniti quod quam \nconsequuntur! Commodi minima excepturi repudiandae velit hic maxime\ndoloremque.",
"content": "Officiis iure rerum voluptates a cumque velit \nquibusdam sed amet tempora. Sit laborum ab, eius fugit doloribus tenetur \nfugiat, temporibus enim commodi iusto libero magni deleniti quod quam \nconsequuntur! Commodi minima excepturi repudiandae velit hic maxime\ndoloremque.",
"status": "published",
"published": "2021-10-01T14:46:34.872576Z"
}
FrontendPostSerializer is gonna look like this
{
"category": {
"name": "django"
},
"id": 45,
"title": "Lorem Ipsum - Lorem ipsum dolor sit amet consectetur",
"image": "http://localhost:8000/media/posts/car_SxXcUTV.jpg",
"slug": "lorem-ipsum-lorem-ipsum-dolor-sit-amet-consectetur",
"author": {
"username": "luigi.verdi"
},
"excerpt": "Officiis iure rerum voluptates a cumque velit \nquibusdam sed amet tempora. Sit laborum ab, eius fugit doloribus tenetur \nfugiat, temporibus enim commodi iusto libero magni deleniti quod quam \nconsequuntur! Commodi minima excepturi repudiandae velit hic maxime\ndoloremque.",
"content": "Officiis iure rerum voluptates a cumque velit \nquibusdam sed amet tempora. Sit laborum ab, eius fugit doloribus tenetur \nfugiat, temporibus enim commodi iusto libero magni deleniti quod quam \nconsequuntur! Commodi minima excepturi repudiandae velit hic maxime\ndoloremque.",
"status": "published",
"published": "2021-10-01T14:46:34.872576Z"
}
What I'm doing atm is using FrontendPostSerializer for showing data in the frontend, for example in a table with category name, author name and title. Instead, I'm using PostSerializer for the backend CRUD.
These are the viewsets I'm using in the views.py
class ManagePosts(viewsets.ModelViewSet):
serializer_class = PostSerializer
parser_classes = [MultiPartParser, FormParser]
def get_object(self, queryset=None, **kwargs):
item = self.kwargs.get('pk')
return get_object_or_404(Post, slug=item)
# Define Custom Queryset
def get_queryset(self):
return Post.objects.all()
class FrontendPosts(viewsets.ModelViewSet):
serializer_class = FrontendPostSerializer
def get_object(self, queryset=None, **kwargs):
item = self.kwargs.get('pk')
return get_object_or_404(Post, slug=item)
# Define Custom Queryset
def get_queryset(self):
return Post.objects.all()
I already tried to use only one serializer, I had this:
class PostSerializer(serializers.ModelSerializer):
author = AuthorSerializer(many=False, read_only=True)
category = CategorySerializer(many=False, read_only=True)
class Meta:
model = Post
fields = ('category', 'id', 'title', 'image', 'slug', 'author', 'excerpt', 'content', 'status', 'published')
but, for example, when I try to create a new post it doesn't work, because category and author are not numbers, but objects.
I'm also gonna put here create.js I have in my React frontend that handles the create submit.
const handleSubmit = (e) => {
e.preventDefault();
let formData = new FormData();
formData.append('category', 1);
formData.append('title', postData.title);
formData.append('slug', postData.slug);
formData.append('author', userInfo.id);
formData.append('excerpt', postData.excerpt);
formData.append('content', postData.content);
if(postImage.image !== null) {
formData.append('image', postImage.image);
}
axiosInstance.post('', formData);
history.push({
pathname: '/admin/',
});
window.location.reload();
};
Is there a better way? I'm sure I can use only one serializer, but I'm not sure how yet.
Thanks!
Actually yes. You can add specific fields you want by using the source attribute. Example:
class PostSerializer(serializers.ModelSerializer):
authorUserName = serializers.CharField(read_only=true, source="author.username")
categoryName = serializers.CharField(read_only=true, source="category.name"
class Meta:
model = Post
fields = (
'category', 'id', 'title',
'image', 'slug', 'author',
'excerpt', 'content', 'status',
'published', 'authorName', 'categoryName')
# Remember add the field that are created
And when you try to get you should get the result like this:
{
"categoryName": "django",
"category": 1,
"id": 45,
"title": "Lorem Ipsum - Lorem ipsum dolor sit amet consectetur",
"image": "http://localhost:8000/media/posts/car_SxXcUTV.jpg",
"slug": "lorem-ipsum-lorem-ipsum-dolor-sit-amet-consectetur",
"authorName": "luigi.verdi",
"author": 4,
"excerpt": "Officiis iure rerum voluptates a cumque velit \nquibusdam sed amet tempora. Sit laborum ab, eius fugit doloribus tenetur \nfugiat, temporibus enim commodi iusto libero magni deleniti quod quam \nconsequuntur! Commodi minima excepturi repudiandae velit hic maxime\ndoloremque.",
"content": "Officiis iure rerum voluptates a cumque velit \nquibusdam sed amet tempora. Sit laborum ab, eius fugit doloribus tenetur \nfugiat, temporibus enim commodi iusto libero magni deleniti quod quam \nconsequuntur! Commodi minima excepturi repudiandae velit hic maxime\ndoloremque.",
"status": "published",
"published": "2021-10-01T14:46:34.872576Z"
}
Related
I got two json objects that I need to combine together based on ID and do count and sort operations on it.
Here is the first object comments:
[
{
"userId": 1,
"id": 1,
"title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
"body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
},
{
"userId": 1,
"id": 2,
"title": "qui est esse",
"body": "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla"
},
{
"userId": 1,
"id": 3,
"title": "ea molestias quasi exercitationem repellat qui ipsa sit aut",
"body": "et iusto sed quo iure\nvoluptatem occaecati omnis eligendi aut ad\nvoluptatem doloribus vel accusantium quis pariatur\nmolestiae porro eius odio et labore et velit aut"
},
{
"userId": 1,
"id": 4,
"title": "eum et est occaecati",
"body": "ullam et saepe reiciendis voluptatem adipisci\nsit amet autem assumenda provident rerum culpa\nquis hic commodi nesciunt rem tenetur doloremque ipsam iure\nquis sunt voluptatem rerum illo velit"
},
]
This is second json object:
[
{
"postId": 1,
"id": 1,
"name": "id labore ex et quam laborum",
"email": "Eliseo#gardner.biz",
"body": "laudantium enim quasi est quidem magnam voluptate ipsam eos\ntempora quo necessitatibus\ndolor quam autem quasi\nreiciendis et nam sapiente accusantium"
},
{
"postId": 1,
"id": 2,
"name": "quo vero reiciendis velit similique earum",
"email": "Jayne_Kuhic#sydney.com",
"body": "est natus enim nihil est dolore omnis voluptatem numquam\net omnis occaecati quod ullam at\nvoluptatem error expedita pariatur\nnihil sint nostrum voluptatem reiciendis et"
},
{
"postId": 1,
"id": 3,
"name": "odio adipisci rerum aut animi",
"email": "Nikita#garfield.biz",
"body": "quia molestiae reprehenderit quasi aspernatur\naut expedita occaecati aliquam eveniet laudantium\nomnis quibusdam delectus saepe quia accusamus maiores nam est\ncum et ducimus et vero voluptates excepturi deleniti ratione"
},
{
"postId": 1,
"id": 4,
"name": "alias odio sit",
"email": "Lew#alysha.tv",
"body": "non et atque\noccaecati deserunt quas accusantium unde odit nobis qui voluptatem\nquia voluptas consequuntur itaque dolor\net qui rerum deleniti ut occaecati"
},
{
"postId": 2,
"id": 5,
"name": "et fugit eligendi deleniti quidem qui sint nihil autem",
"email": "Presley.Mueller#myrl.com",
"body": "doloribus at sed quis culpa deserunt consectetur qui praesentium\naccusamus fugiat dicta\nvoluptatem rerum ut voluptate autem\nvoluptatem repellendus aspernatur dolorem in"
},
{
"postId": 2,
"id": 6,
"name": "repellat consequatur praesentium vel minus molestias voluptatum",
"email": "Dallas#ole.me",
"body": "maiores sed dolores similique labore et inventore et\nquasi temporibus esse sunt id et\neos voluptatem aliquam\naliquid ratione corporis molestiae mollitia quia et magnam dolor"
},
]
Object one is basically posts with poster details and object two is comments with commenter details.
So expected that object one has one to many relationships with second object. For example one post has many comments. This relationship is based on id in object one is postId in object two. The ultimate objective is to count and sort post by number of comments.
I attempt the problem with simple for loops and creating new json object, I managed to combine them together, but I dont know how to count and sort them properly.
in the views:
for i in posts:
if (id==postId):
newobj.append(objtwo[i])
count+=1
else:
newobj.append(count)
count=0
Normally I use django ORM to sort this but I dont have access to the database and model of the table. How to count and sort the new object so it can return list of posts with most comments counts and descend to lower comments counts?
Assuming your posts and comments data structures are lists, you can use python's defaultdict to count the comments. Then, use posts.sort(key=...) to sort your posts based on the collected counts using the key parameter. Altogether, it could like like this:
import json
from collections import defaultdict
posts = [ ... ]
comments = [ ... ]
# data structure to count the to comments
# automatically initializes to 0
comments_per_post = defaultdict(int)
# iterate through the comments to increase the count for the posts
for comment in comments:
comments_per_post[comment['postId']] += 1
# add comment count to post
for post in posts:
post['number_of_comments'] = comments_per_post[post['id']]
# sort the posts based on the counts collected
posts.sort(key=lambda post: post['number_of_comments'], reverse=True)
# print them to verify
# number of comments per Post will be in the `number_of_comments` key on the post dict.
print(json.dumps(posts, indent=2))
Note: this sorts the posts array in-place. If you don't want this, you can use sorted_posts = sorted(posts, key=... instead.
My answer is very similar to Byted's answer.
I would use Counter from the built-in collections to count the number of postIds in the second object.
Then sort the first object by using these counts from the previous step as a sorting key. Counter object returns 0 if a key is not present in it, so just use it as a lookup as a sorting key. The negative sign ensures a descending order (because sorted() sorts in ascending order by default).
import json
from collections import Counter
# count the comments
counts = Counter([d['postId'] for d in objtwo])
# add the counts to each post
for d in objone:
d["number of comments"] = counts[d['id']]
# sort posts by number of comments in descending order
objone.sort(key=lambda x: -x['number of comments'])
# convert to json
json.dumps(objone, indent=4)
Intermediate output for this input:
print(counts)
# Counter({1: 4, 2: 2})
I'm new at ApacheSpark. Currently, I'm performing some statistical analysis for a text. I start reading the text and storing it in a variable as follows:
loremRDD = sc.textFile(fileName, 8).map(removePunctuation).filter(lambda x: len(x)>0)
#First 10 lines
loremRDD.take(10)
The result is a PythonRDD[66] at RDD at PythonRDD.scala:53 variable. Below there are the first 10 lines of the text:
['aut minima deleniti et autem minus illo esse dolores eligendi corrupti dolore minima nostrum eos nobis nam nihil aspernatur nam ut quae sint laborum ut dolores error possimus aperiam consequatur',
'pariatur sed quo non itaque qui pariatur saepe ad quis consequatur nihil iste molestias et eos ut expedita vel reiciendis dolorem enim doloribus quam architecto aperiam',
'sed repudiandae pariatur similique est aut sequi animi in aperiam enim ipsa enim dolorem inventore aut quo odio in consequatur et',
'aspernatur ad esse et aliquid itaque dolores rerum quia commodi explicabo non magnam nostrum consectetur non sint eum nulla et aut quis doloribus itaque nulla molestiae quis est est quo facilis incidunt a ipsa in itaque sed aut nobis facere dignissimos atque unde cum ea vero',
'tenetur vel quod voluptatum laudantium dolores neque aut est modi qui aperiam itaque aperiam quae ratione doloremque aut delectus quas qui',
'qui placeat vel ipsam praesentium sint recusandae dicta minus praesentium omnis sequi a sed veritatis porro ab et officia esse commodi pariatur sequi cumque',
'mollitia facilis amet deleniti quia laborum commodi et molestias maxime quia dignissimos inventore neque libero deleniti ad quo corrupti numquam quis accusantium',
'architecto harum sunt et enim nisi commodi et id reprehenderit illum molestias illo facilis fuga eum illum quasi fugit qui',
'modi voluptatem quia et saepe inventore sed quo ea debitis explicabo vel perferendis commodi exercitationem sequi eum dolor cupiditate ab molestiae nemo ullam neque hic ipsa cupiditate dolor molestiae neque nam nobis nihil mollitia unde',
'voluptates quod in ipsum dicta fuga voluptatibus sint consequatur quod optio molestias nostrum repellendus consequatur aliquam fugiat provident omnis minus est quisquam exercitationem eum voluptas fugit quae eveniet perspiciatis assumenda maxime']
I need to know how many different words have twice the letter 'o'. For example, the word dolorem has twice the letter 'o'.
At the moment, I´ve created distintWordsRDD which stores all differents words contained in the text as follows:
loremWordsRDD = loremRDD.flatMap(lambda x: x.split(' '))
distintWordsMapRDD = loremWordsRDD.map(lambda word: (word,1)).reduceByKey(lambda a,b:a+b)
distintWordsRDD=distintWordsMapRDD.keys().distinct()
# Showing 8 first words
print(distintWordsRDD.take(8))
The result of the 8 first words is:
['tempora', 'sapiente', 'vitae', 'nisi', 'quidem', 'consectetur', 'perferendis', 'debitis']
My problem is that I don´t know how to retrieve from distintWordsRDD a list with the words that have two 'o'.
The following should work:
your_text=''.join(your_original_list_of_texts)
result=[i for i in your_text.split() if i.count('o')==2]
print(result)
['dolores', 'dolore', 'dolores', 'dolorem', 'doloribus', 'dolorem', 'odio']
However the text that you provided is split to many subtexts ('sometext1', 'sometext2', 'sometext3, etc) and it needs some additional work so that it will come to a simple text format ('alltext')
If you provide exact details of your input text, i will adjust the code so that it will work properly with the input without additional manual work
If you only have one string sentence:
results = set(word for word in sentence.split() if word.count('o') == 2)
If you have a list sentences of strings (which is what you show in your question):
results = set(
word
for sentence in sentences
for word in sentence.split()
if word.count('o') == 2
)
I'm using set to unify the results.
Output for the list of sentences in your example:
{'odio', 'dolorem', 'dolore', 'doloremque', 'dolor', 'doloribus', 'optio', 'commodi', 'porro', 'dolores'}
If you need a list then just convert the set in a list: results = list(results)).
I managed to solve this problem doing the following:
results = distintWordsRDD.filter(lambda word: word.count('o')==2)
print (results.collect())
print(results.count())
Result:
['porro', 'odio', 'laboriosam', 'doloremque', 'doloribus', 'dolores', 'dolor', 'corporis', 'commodi', 'optio', 'dolorum', 'dolore', 'dolorem']
13
Example:
print("Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo."
Outputs:
Sed ut perspiciatis unde omnis iste natus error sit voluptatem
accusantium doloremque laudantium, totam rem aperiam, eaque
ipsa quae ab illo inventore veritatis et quasi architecto
beatae vitae dicta sunt explicabo.
Desired output:
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.
Directly go through this page
https://github.com/jupyter/notebook/issues/106
Type in your cmd prompt or equivalent: jupyter --config-dir to get your jupyter settings location.
Create a folder nbconfig inside the settings location /.jupyter. Inside, create a file notebook.json with the following
{
"MarkdownCell": {
"cm_config": {
"lineWrapping": false
}
},
"CodeCell": {
"cm_config": {
"lineWrapping": false
}
}
}
Restart jupyter and reload, then try
You need HTML output that has some CSS applied. Here is the code that you may try:
import IPython.display as dp
long_txt = "Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo."
outp = dp.HTML("<style>.nowrap{white-space:nowrap;}</style><span class='nowrap'>" +long_txt+ "</span>")
Now you get outp as an HTML object. You can render it and get the long one-line text.
outp
The output will be:
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.
Hope it helps.
Trying to do a recursive filter query on RethinkDB with they Python wrapper. Having a lot of trouble getting it work.
Tried a lot of variations of the query, to no avail. Essentially, I'm trying to find the rows which do not have a document nested under label with a particular user_id.
In plain english: if the current user already labeled this example, don’t return it to them again.
My non-working query:
open_tasks = rdbt \
.order_by(index=r.desc('labels_completed')) \
.filter(r.row['locked'] == False) \
.filter(lambda task:
task['labels']['user_id'] != current_user.id) \
.limit(qty) \
.run(conn)
My dataset
[
{
"id": "e54893b4-b1d0-49c5-b6aa-9aa9e7d2b73b",
"image": "https://dl.dropboxusercontent.com/u/5822/crowdlabeler/ABLXOTODWJKTXECYZTST.jpg",
"labels": [
{
"account_qty_labeled": 54,
"account_signup_date": "Tue Aug 04 2015 10:12:25 GMT-04:00",
"compensation": 0.01,
"dataset_id": 144,
"label": {
"$$hashKey": "object:45",
"answer": "Yes",
"selected": true
},
"label_duration_sec": 3,
"labeled_at": "Wed Aug 05 2015 16:26:04 GMT-05:00",
"sess_duration_sec": 3,
"sess_qty_labeled": 0,
"user_id": 1
}
],
"labels_completed": 0,
"locked": false,
"text": "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Cupiditate adipisci vero minus laudantium reprehenderit exercitationem eius, suscipit facilis laboriosam consequuntur, eligendi quis mollitia excepturi deserunt dicta, dolorem quaerat pariatur provident sint explicabo. Magnam possimus dolorum beatae quidem excepturi quibusdam dolore reprehenderit accusantium quae ad libero, voluptatum laborum, incidunt, voluptate reiciendis."
},
{
"id": "9f08869e-79fd-49c0-a184-c43d2a1c95cf",
"image": "https://dl.dropboxusercontent.com/u/5822/crowdlabeler/ACSGHDYECQWQXDHIOBYC.jpg",
"labels": [],
"labels_completed": 0,
"locked": false,
"text": "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Cupiditate adipisci vero minus laudantium reprehenderit exercitationem eius, suscipit facilis laboriosam consequuntur, eligendi quis mollitia excepturi deserunt dicta, dolorem quaerat pariatur provident sint explicabo. Magnam possimus dolorum beatae quidem excepturi quibusdam dolore reprehenderit accusantium quae ad libero, voluptatum laborum, incidunt, voluptate reiciendis."
},
{
"id": "9fba0a39-4cfd-4a97-b48f-e8bf2b0d46c5",
"image": "https://dl.dropboxusercontent.com/u/5822/crowdlabeler/ADMNIUYKUHAIOHMAFXBK.jpg",
"labels": [],
"labels_completed": 0,
"locked": false,
"text": "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Cupiditate adipisci vero minus laudantium reprehenderit exercitationem eius, suscipit facilis laboriosam consequuntur, eligendi quis mollitia excepturi deserunt dicta, dolorem quaerat pariatur provident sint explicabo. Magnam possimus dolorum beatae quidem excepturi quibusdam dolore reprehenderit accusantium quae ad libero, voluptatum laborum, incidunt, voluptate reiciendis."
}
]
Thank you for your help!
This was a tough one but the solution ended up being two-fold.
A slight modification to the schema when saving, then using RethinkDB's contains method.
Here is the modified query that works well.
open_tasks = rdbt \
.order_by(index=r.desc('labels_completed')) \
.filter(r.row['locked'] == False) \
.filter(lambda task:
r.not_(task['labeler_ids'].contains(current_user.id))) \
.limit(qty) \
.run(conn)
When I submit the following text in my textarea box on the windows GAE launcher at http://localhost:8080 it displays fine.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus a dolor eget diam
condimentum varius. Proin malesuada dictum ante, sed commodo purus vestibulum in.
Sed nibh dui, volutpat eu porta eu, molestie ut lacus. Vivamus iaculis urna ut tellus
blandit eu at nisl. Fusce eros libero, aliquam vitae hendrerit vitae, posuere ac diam.
Vivamus sagittis, felis in imperdiet pellentesque, eros nibh porttitor nisi, id
tristique leo libero a ligula. In in elit et velit auctor lacinia eleifend cursus mauris. Mauris
pellentesque lorem et augue placerat ultrices. Nam sed quam nisl, eget elementum felis.
Integer sapien ipsum, aliquet quis viverra quis, adipiscing eget sapien. Nam consequat
lacinia enim, id viverra nisl molestie feugiat.
When my code is deployed on GAE after I hit the submit button it displays like this:
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus a dolor eg=
et diam condimentum varius. Proin malesuada dictum ante, sed commodo purus =
vestibulum in. Sed nibh dui, volutpat eu porta eu, molestie ut lacus. Vivam=
us iaculis urna ut tellus tempor blandit eu at nisl. Fusce eros libero, ali=
quam vitae hendrerit vitae, posuere ac diam. Vivamus sagittis, felis in imp=
erdiet pellentesque, eros nibh porttitor nisi, id tristique leo libero a li=
gula. In in elit et velit auctor lacinia eleifend cursus mauris. Mauris pel=
lentesque lorem et augue placerat ultrices. Nam sed quam nisl, eget element=
um felis. Integer sapien ipsum, aliquet quis viverra quis, adipiscing eget =
sapien. Nam consequat lacinia enim, id viverra nisl molestie feugiat.
Implementation Description below:
I am using the jinja2 engine. I have autescape = false:
jinja_env = jinja2.Environment(loader = jinja2.FileSystemLoader(template_dir), autoescape = False)
I get the content from a textarea element. Here is how it is set in my template:
<label>
<div>Information</div>
<textarea name="information">{{r.information}}</textarea>
</label>
I retrieve the string using:
information = self.request.get('information')
I committ the string to the data store
r.information = information
r.put()
When displaying it again for editing I use the same template code:
<label>
<div>Information</div>
<textarea name="information">{{r.information}}</textarea>
</label>
Everything works great locally. But when I deploy it to the google app engine I am getting some strange results. Where do those = signs come from I wonder?
EDIT:
For clarification it is putting =CRLF at the end of every line.
*EDIT 2: *
Here is the code from comment 21 of the bug:
def from_fieldstorage(cls, fs):
"""
Create a dict from a cgi.FieldStorage instance
"""
obj = cls()
if fs.list:
# fs.list can be None when there's nothing to parse
for field in fs.list:
if field.filename:
obj.add(field.name, field)
else:
# first, set a common charset to utf-8.
common_charset = 'utf-8'
# second, check Content-Transfer-Encoding and decode
# the value appropriately
field_value = field.value
transfer_encoding = field.headers.get(
'Content-Transfer-Encoding', None)
if transfer_encoding == 'base64':
field_value = base64.b64decode(field_value)
if transfer_encoding == 'quoted-printable':
field_value = quopri.decodestring(field_value)
if field.type_options.has_key('charset') and \
field.type_options['charset'] != common_charset:
# decode with a charset specified in each
# multipart, and then encode it again with a
# charset specified in top level FieldStorage
field_value = field_value.decode(
field.type_options['charset']).encode(common_charset)
# TODO: Should we take care of field.name here?
obj.add(field.name, field_value)
return obj
multidict.MultiDict.from_fieldstorage = classmethod(from_fieldstorage)
You might be falling foul of this bug
The workaround in comment 21 has worked for me in the past, and recent comments indicate it still does.