Why would using a random seed with other variables be bad for ecrypting if you can't guess the key?
Your option has the flaw of allowing either key recovery, or RNG state recovery, or both. Cryptographically strong constructions do not allow key recovery with less effort than brute force, even with millions or billions of known message pairs. In your case an attack will most likely succeed in a short period of time. It took me only a few hours to completely break something quite similar that at first glance appeared much stronger than this, but suffered from the same key recovery attack with modest computing power.

Since Python does not have native encryption, you kind of have to roll your own from the standard library, or use an addon library such as PyCrypto.

If you do not have the option of using an addon library, a stream cipher can be built from HMAC-SHA512, plus a nonce and a some counters. The high level overview is:

Generate salt and nonce (nonce can be 128-bit salt + 32-bit message counter).
The salt should be randomly generated, if a good RNG is not available in Python, use random.org
Salt needs to be stored, it is used to generate the encryption key for all messages.
Message counter is very important to keep current.

Generate key from password and salt using PBKFD2. If you are using a true random key and not a password you can skip this part.
key = hashlib.pbkdf2_hmac('sha512', 'Password', 'Salt', 32768)[:44]

I use truncated HMAC to generate 44-byte blocks, and a 32-bit message counter. The reason I truncate is to hide 160-bits of the hash state, which may provide additional security, but slows it down to around 2/3 of what is capable.
Find out how many blocks of keystream are required to encrypt the message. A 113-byte message would need 3 44-byte blocks

hm0 = hmac.new(key, 'Nonce', hashlib.sha512)
hm = hm0.copy()
hm.update('BlockCounter')
KSBlock = hm.digest()[:44]

Loop the last 3 lines for each block of keystream you need, XORing the plaintext with the keystream to generate the ciphertext with the same length as the plaintext. Once that is done, prepend (or include in some way) the message counter. Decryption and encryption are the same operation, with the difference being you are using a specific message counter instead of a new one. You can also decode blocks out of order, which can be useful for large messages. Text readable encoding such as Base64 can be applied after encryption.

This example ties the encryption key directly to the password, which I assume is what you are looking for. Other methods use the password to encrypt a random key, then the key encrypts the message. This would allow for the password to be changed without having to reencrypt the entire message. On the other hand it needs a good random number generator.

The 32-bit counters give you a max message size around 176GB, and over 4 billion messages before the nonce counter runs out. This should be more than enough for a single person using a web application. Note that I am not a Python programmer, and the code samples here may not be proper syntax, and are more of a pseudocode. I would still highly recommend a cryptographic library and use AES-CTR instead, but sometimes you have no option.